﻿using JinYuan.DataConvertLib;
using log4net.Core;
using log4net.Repository.Hierarchy;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PLCCommunication.MQTT;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Xml.Linq;
using static WindowsService1.MqttDataService;

namespace WindowsService1
{
    public partial class Service1 : ServiceBase
    {
        private readonly List<Task> _tasks = new List<Task>();
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();

        private PLCWrapper _plcWrapper;
        private MqttClientWrapper mqttClient = null; // 保留用于向后兼容
        private Dictionary<string, MqttClientWrapper> mqttClients = new Dictionary<string, MqttClientWrapper>();
        private Dictionary<string, MqttClientGroupConfig> _mqttClientGroups = new Dictionary<string, MqttClientGroupConfig>();
        private Dictionary<MqttClientWrapper, MqttMessageQueue> clientMessageQueues = new Dictionary<MqttClientWrapper, MqttMessageQueue>();
        private Dictionary<string, List<ReceivedMqttMessage>> clientGroupMessages = new Dictionary<string, List<ReceivedMqttMessage>>();
        private readonly object _clientGroupMessagesLock = new object();
        private Dictionary<string, CancellationTokenSource> clientGroupCollectionTasks = new Dictionary<string, CancellationTokenSource>();
        private System.Threading.Timer _periodicTimer;

        // 添加任务状态跟踪
        private bool _dataCollectionTaskStarted = false;

        // 添加消息队列实例
        private MqttMessageQueue _mqttMessageQueue;
        
        // 添加接收消息处理
        private readonly List<ReceivedMqttMessage> _receivedMessages = new List<ReceivedMqttMessage>();
        private readonly object _receivedMessagesLock = new object();
        
        // 消息接收事件
        public event Action<ReceivedMqttMessage> OnMqttMessageReceived;

        private List<TypeConfig> _typeConfigs;  // 所有Type配置的扁平化列表
        private Dictionary<AcquisitionType, CollectionGroupConfig> _collectionGroups;
        private Dictionary<AcquisitionType, Dictionary<string, string>> _plcAddresses;
        private Dictionary<AcquisitionType, AcquisitionTypeConfig> _acquisitionTypeConfigs;


        private AcquisitionType[] AcqTypes = null;

        private const int ReconnectionInterval = 5000; // 5 seconds
        private const int MaxReconnectAttempts = 3;

        public string PlcIpAddress = "127.0.0.1";
        public int PlcPort = 9600;


        public string MQTTServerAddress = "127.0.0.1";
        public int MQTTServerPort = 1883;
        public string ClientId = "601UPW01";
        // 主题配置已迁移到Config.xml动态配置中
        private string DEFAULT_ROBOT_TOPIC_PREFIX = "EVE/60J/ROBOT/";


        public MqttCredential credentials = null;

        public string BU_id = "EVE2BU";
        public string District_id = "QJ";
        public string Factory_id = "60J";
        public string Production_line_id = "MW-602";
        public string Work_Center_id = "602VIM01";
        public string production_processes_id = "P020";
        public string Device_name;

        public int ThreadInterval = 50;
        public static bool SwitchLog = false;

        private string _lastRobotStatus = "0";
        private string _lastHandStatus = "0";
        private Dictionary<string, RobotActionData> _lastActionData = new Dictionary<string, RobotActionData>();
        private const string _robotName = "J01";
        private const string _uploadMode = "A";

        private static readonly string[] BASE_ACTIONS = { "A", "B", "C", "D", "E", "F", "G", "H" };

        private static readonly Dictionary<string, double> ACTION_TIMEPOINTS = new Dictionary<string, double>
        {
            {"A", 1.5},
            {"B", 0.5},
            {"C", 1.5},
            {"D", 2.5},
            {"E", 1.5},
            {"F", 0.5},
            {"G", 1.5},
            {"H", 2.5}
        };

        private class RobotActionData
        {
            public string Action { get; set; }
            public double Timepoint { get; set; }
        }

        // 接收到的MQTT消息结构
        public class ReceivedMqttMessage
        {
            public DateTime Timestamp { get; set; }
            public string Topic { get; set; }
            public string Message { get; set; }
            public string Source { get; set; }
            public AcquisitionType? MessageType { get; set; }
            public bool IsProcessed { get; set; } = false;
        }

        // MQTT参数下发消息结构（服务端→上位机）
        public class ParameterDownloadMessage
        {
            public ParameterHead Head { get; set; }
            public List<ParameterBody> Body { get; set; }
        }

        // MQTT参数回复消息结构（上位机→服务端）
        public class ParameterResponseMessage
        {
            public ParameterHead Head { get; set; }
            public List<ParameterResponseBody> Body { get; set; }
        }

        // 参数消息头
        public class ParameterHead
        {
            public string MethodName { get; set; }       // 方法名称
            public string BuStation { get; set; }        // 站点
            public string FactoryCode { get; set; }      // 工厂编码
            public string ProductionLineCode { get; set; } // 产线编码
            public string ProcessCode { get; set; }      // 工序编码
            public string EquipmentCode { get; set; }    // 设备编码
            public string MessageId { get; set; }        // 消息ID
        }

        // 参数消息体（下发）
        public class ParameterBody
        {
            public string ItemCode { get; set; }         // 参数项目代码
            public string ItemValue { get; set; }        // 参数数据值
        }

        // 参数消息体（回复）
        public class ParameterResponseBody : ParameterBody
        {
            public string WriteResult { get; set; }      // 写入结果（1=成功，0=失败）
        }

        // 参数上传消息结构（上位机→IOT）
        public class ParameterUploadMessage
        {
            public List<ParameterUploadTagList> taglist { get; set; }
            public string bu_id { get; set; }
            public string district_id { get; set; }
            public string factory_id { get; set; }
            public string production_line_id { get; set; }
            public string production_processes_id { get; set; }
            public string work_center_id { get; set; }
            public string station_id { get; set; }
            public string device_name { get; set; }
        }

        public class ParameterUploadTagList
        {
            public Dictionary<string, object> collection_items { get; set; }
            public string device_time { get; set; }
        }

        // MQTT客户端组配置类
        public class MqttClientGroupConfig
        {
            public string Name { get; set; }                     // 客户端组名称
            public string ClientId { get; set; }                 // 客户端ID
            public string Description { get; set; }              // 描述
            public List<string> AcquisitionTypes { get; set; }   // 处理的采集类型
            public bool IsEnabled { get; set; } = true;          // 是否启用
            public int CollectionIntervalMs { get; set; } = 1000; // 采集间隔毫秒数，默认1秒
        }

        // 扩展的采集类型配置类


        private readonly Dictionary<string, RobotState> _lastRobotStates = new Dictionary<string, RobotState>();
        
        // 消息处理器映射字典 - 将processType映射到处理方法
        private Dictionary<string, Action<ReceivedMqttMessage>> _messageHandlers;
        
        // MQTT主题日志记录器
        private readonly MqttTopicLogger _mqttTopicLogger = MqttTopicLogger.Instance;

        /// <summary>
        /// 初始化消息处理器映射
        /// </summary>
        private void InitializeMessageHandlers()
        {
            _messageHandlers = new Dictionary<string, Action<ReceivedMqttMessage>>
            {
                { "PPM", ProcessPPMMessage },
                { "Float", ProcessAxisMessage },  // Axis和Cylinder都使用Float类型
                { "Robot", ProcessRobotMessage },
                { "ParameterDown", ProcessParameterDownloadMessageWrapper },
                { "ParameterUpload", ProcessParameterUploadMessage }
            };
        }

        private class RobotState
        {
            public string RobotStatus { get; set; }
            public string CurrentAction { get; set; }
            public DateTime Timestamp { get; set; }
            public short HandStatus { get; set; }
            public double TimePoint { get; set; }
        }

        public Service1()
        {
            InitializeComponent();
            ServiceName = "TestMqttService";
            CanStop = true; // 服务可以被停止
            CanPauseAndContinue = false;
            AutoLog = true;

          
        }
        public void Start()
        {
            OnStart(null);
        }

        protected override void OnStart(string[] args)
        {
            _mqttTopicLogger.WriteServiceStatus("WindowsService1", "启动中", $"启动时间: {DateTime.Now}");
            
            // 启动日志清理任务（每天执行一次）
            Task.Run(async () =>
            {
                while (!_cts.Token.IsCancellationRequested)
                {
                    try
                    {
                        _mqttTopicLogger.CleanupOldLogs(30); // 保留30天的日志
                        await Task.Delay(TimeSpan.FromDays(1), _cts.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        break;
                    }
                    catch (Exception ex)
                    {
                        _mqttTopicLogger.WriteSystemError($"日志清理任务出错: {ex.Message}", ex);
                        await Task.Delay(TimeSpan.FromHours(1), _cts.Token);
                    }
                }
            });
            
            TestConfigLoading(); // 添加配置文件测试
            InitializeConfig();

            // 初始化消息处理器映射
            InitializeMessageHandlers();

            // 打印系统诊断信息
            PrintSystemDiagnostics();
            
            // 记录配置加载完成
            _mqttTopicLogger.WriteConfigOperation("配置加载", "系统配置", "加载完成");
            _mqttTopicLogger.WriteSystemInfo("系统初始化完成，准备启动各项服务");
            
            // 验证配置完整性
            ValidateConfigurationCompleteness();
            
            _plcWrapper = new PLCWrapper(PlcIpAddress, PlcPort);
            // 初始化MQTT消息队列，设置发送间隔为500毫秒
            _mqttMessageQueue = new MqttMessageQueue(500, SendMqttAsync);
            InitializeTask();
            InitializeMQTT();

            // 先初始化PLC连接，连接成功后再启动数据采集任务
            InitializePLC();
           
            _mqttTopicLogger.WriteServiceStatus("WindowsService1", "启动完成", $"完成时间: {DateTime.Now}");
        }

     

       

        /// <summary>
        /// 打印系统诊断信息
        /// </summary>
        private void PrintSystemDiagnostics()
        {
            try
            {
                _mqttTopicLogger.WriteSystemInfo("=== 系统诊断信息 ===");
                _mqttTopicLogger.WriteConfigOperation("系统配置", "PLC配置", $"{PlcIpAddress}:{PlcPort}");
                _mqttTopicLogger.WriteConfigOperation("系统配置", "MQTT配置", $"{MQTTServerAddress}:{MQTTServerPort}");
                _mqttTopicLogger.WriteConfigOperation("系统配置", "客户端ID", ClientId);
                _mqttTopicLogger.WriteConfigOperation("系统配置", "线程间隔", $"{ThreadInterval}ms");
                
                _mqttTopicLogger.WriteSystemInfo($"已配置的采集类型数量: {_acquisitionTypeConfigs?.Count ?? 0}");
                if (_acquisitionTypeConfigs != null)
                {
                    foreach (var config in _acquisitionTypeConfigs)
                    {
                        _mqttTopicLogger.WriteSystemInfo($"  - {config.Key}: 启用={config.Value.IsEnabled}, 处理类型={config.Value.ProcessType}, 主题={config.Value.MqttTopic}");
                    }
                }

                _mqttTopicLogger.WriteSystemInfo($"已配置的采集组数量: {_collectionGroups?.Count ?? 0}");
                if (_collectionGroups != null)
                {
                    foreach (var group in _collectionGroups)
                    {
                        _mqttTopicLogger.WriteSystemInfo($"  - {group.Key}: 地址={group.Value.StartAddress}, 长度={group.Value.Length}");
                    }
                }

                _mqttTopicLogger.WriteSystemInfo($"已配置的类型配置数量: {_typeConfigs?.Count ?? 0}");
                _mqttTopicLogger.WriteServiceStatus("数据采集任务", (_dataCollectionTaskStarted ? "已启动" : "未启动"));
                _mqttTopicLogger.WriteSystemInfo("=== 诊断信息结束 ===");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"打印诊断信息时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 验证动态配置完整性
        /// </summary>
        private void ValidateConfigurationCompleteness()
        {
            try
            {
                _mqttTopicLogger.WriteConfigOperation("配置验证", "动态配置完整性验证", "开始");
                bool hasConfigurationErrors = false;

                // 验证客户端组配置
                if (_mqttClientGroups == null || _mqttClientGroups.Count == 0)
                {
                    _mqttTopicLogger.WriteSystemError("未找到任何MQTT客户端组配置！");
                            hasConfigurationErrors = true;
                }
                else
                {
                    _mqttTopicLogger.WriteConfigOperation("配置验证", "客户端组", $"发现 {_mqttClientGroups.Count} 个动态创建的客户端组");
                    foreach (var clientGroup in _mqttClientGroups)
                    {
                        _mqttTopicLogger.WriteConfigOperation("配置验证", "客户端组详情", $"{clientGroup.Key}: {clientGroup.Value.ClientId} ({string.Join(",", clientGroup.Value.AcquisitionTypes)})");
                    }
                }

                // 验证采集类型配置
                if (_acquisitionTypeConfigs == null || _acquisitionTypeConfigs.Count == 0)
                {
                    _mqttTopicLogger.WriteSystemError("未找到任何采集类型配置！");
                            hasConfigurationErrors = true;
                        }
                else
                        {
                    _mqttTopicLogger.WriteConfigOperation("配置验证", "采集类型", $"发现 {_acquisitionTypeConfigs.Count} 个动态创建的采集类型");
                    foreach (var typeConfig in _acquisitionTypeConfigs)
                            {
                        _mqttTopicLogger.WriteConfigOperation("配置验证", "采集类型详情", $"{typeConfig.Key}: Topic={typeConfig.Value.MqttTopic}, Robot={typeConfig.Value.IsRobot}, ProcessType={typeConfig.Value.ProcessType}");
                            }
                            }

                // 验证CollectionGroup配置
                if (_collectionGroups == null || _collectionGroups.Count == 0)
                            {
                    _mqttTopicLogger.WriteSystemError("未找到任何CollectionGroup配置！");
                                hasConfigurationErrors = true;
                        }
                        else
                        {
                    _mqttTopicLogger.WriteConfigOperation("配置验证", "CollectionGroup", $"发现 {_collectionGroups.Count} 个CollectionGroup");
                    foreach (var group in _collectionGroups)
                    {
                        var acquisitionType = group.Key;
                        var groupConfig = group.Value;
                        _mqttTopicLogger.WriteConfigOperation("配置验证", "CollectionGroup详情", $"{acquisitionType}: {groupConfig.StartAddress}, Length={groupConfig.Length}, Types={groupConfig.Types?.Count ?? 0}");

                        // 验证采集类型是否有对应的AcquisitionTypeConfig
                        if (!_acquisitionTypeConfigs.ContainsKey(acquisitionType))
                        {
                            _mqttTopicLogger.WriteConfigOperation("配置验证", "验证通过", $"✓ 采集类型 {acquisitionType} 配置验证通过");
                        }
                    }
                }

                // 验证类型配置数量
                if (_typeConfigs == null || _typeConfigs.Count == 0)
                {
                    _mqttTopicLogger.WriteSystemError("未找到任何Type配置！");
                    hasConfigurationErrors = true;
                }
                else
                {
                    _mqttTopicLogger.WriteConfigOperation("配置验证", "Type配置", $"发现 {_typeConfigs.Count} 个Type配置");
                }

                if (hasConfigurationErrors)
                {
                    _mqttTopicLogger.WriteSystemError("=== 动态配置验证失败，存在配置错误！ ===");
                    throw new InvalidOperationException("动态配置验证失败，请检查启用的设备配置");
                }
                else
                {
                    _mqttTopicLogger.WriteConfigOperation("配置验证", "验证完成", "=== 动态配置验证通过！所有配置项均正确创建 ===");
                    _mqttTopicLogger.WriteConfigOperation("配置验证", "验证总结", $"客户端组({_mqttClientGroups?.Count ?? 0})，采集类型({_acquisitionTypeConfigs?.Count ?? 0})，Collection组({_collectionGroups?.Count ?? 0})，类型配置({_typeConfigs?.Count ?? 0})");
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"动态配置验证时出错: {ex.Message}", ex);
                throw; // 重新抛出异常，阻止服务启动
            }
        }

        protected override async void OnStop()
        {
            _mqttTopicLogger.WriteServiceStatus("WindowsService1", "停止中", $"停止时间: {DateTime.Now}");
            
            // 停止所有客户端组的数据采集任务
            if (_dataCollectionTaskStarted)
            {
                _mqttTopicLogger.WriteServiceStatus("数据采集任务", "停止中", "停止所有客户端组的数据采集任务");
                
                // 停止各个客户端组的采集任务
                foreach (var taskPair in clientGroupCollectionTasks)
                {
                    try
                    {
                        _mqttTopicLogger.WriteServiceStatus("数据采集任务", "停止中", $"停止客户端组 {taskPair.Key} 的采集任务");
                        taskPair.Value.Cancel();
                    }
                    catch (Exception ex)
                    {
                        _mqttTopicLogger.WriteSystemError($"停止客户端组 {taskPair.Key} 采集任务时出错: {ex.Message}", ex);
                    }
                }
                
                // 停止主采集任务
                _cts.Cancel();
                _dataCollectionTaskStarted = false;
                
                _mqttTopicLogger.WriteServiceStatus("数据采集任务", "已停止", "所有客户端组采集任务已停止");
            }
            
            _periodicTimer?.Dispose();
            
            // 停止消息队列处理
            _mqttMessageQueue?.Stop();
            _mqttTopicLogger.WriteServiceStatus("MQTT消息队列", "已停止", "MQTT消息队列已停止");
            
            // 停止 PLC 读取
            if (_plcWrapper != null)
            {
                _plcWrapper.Disconnect();
                _mqttTopicLogger.WriteServiceStatus("PLC通讯", "已停止", "PLC 通讯已停止");
            }
            
            if (mqttClient != null)
            {
                await mqttClient.Disconnect();
                _mqttTopicLogger.WriteServiceStatus("MQTT连接", "已关闭", "MQTT 连接已关闭");
            }
            
            _mqttTopicLogger.WriteServiceStatus("WindowsService1", "停止完成", $"完成时间: {DateTime.Now}");
        }

        /// <summary>
        /// 主题诊断 - 检查所有主题订阅状态
        /// </summary>
        /// <returns>主题诊断报告</returns>
        public Dictionary<string, object> GetTopicDiagnostics()
        {
            var diagnostics = new Dictionary<string, object>();
            
            try
            {
                var topicInfo = new Dictionary<string, object>();
                
                // 检查每个采集类型的主题配置
                foreach (var config in _acquisitionTypeConfigs)
                {
                    var typeInfo = new Dictionary<string, object>
                    {
                        ["AcquisitionType"] = config.Key.ToString(),
                        ["MqttTopic"] = config.Value.MqttTopic ?? "未配置",
                        ["IsRobot"] = config.Value.IsRobot,
                        ["RobotTopicPrefix"] = config.Value.RobotTopicPrefix ?? "未配置",
                        ["RequiresSubscription"] = config.Value.RequiresSubscription,
                        ["IsEnabled"] = config.Value.IsEnabled,
                        ["ProcessType"] = config.Value.ProcessType
                    };
                    
                    // 检查是否有对应的客户端组
                    var hasClientGroup = _mqttClientGroups.Values.Any(group => 
                        group.AcquisitionTypes.Contains(config.Key.ToString()));
                    typeInfo["HasClientGroup"] = hasClientGroup;
                    
                    topicInfo[config.Key.ToString()] = typeInfo;
                }
                
                diagnostics["TopicConfigurations"] = topicInfo;
                
                // 检查客户端组订阅状态
                var clientGroupInfo = new Dictionary<string, object>();
                foreach (var group in _mqttClientGroups)
                {
                    var groupInfo = new Dictionary<string, object>
                    {
                        ["ClientId"] = group.Value.ClientId,
                        ["IsEnabled"] = group.Value.IsEnabled,
                        ["AcquisitionTypes"] = group.Value.AcquisitionTypes,
                        ["HasMqttClient"] = mqttClients.ContainsKey(group.Key)
                    };
                    
                    if (mqttClients.TryGetValue(group.Key, out var client))
                    {
                        groupInfo["ClientConnected"] = client.IsConnected;
                    }
                    
                    clientGroupInfo[group.Key] = groupInfo;
                }
                
                diagnostics["ClientGroups"] = clientGroupInfo;
                
                // 检查可能的主题冲突
                var topicConflicts = new List<string>();
                var usedTopics = new Dictionary<string, List<string>>();
                
                foreach (var config in _acquisitionTypeConfigs.Values)
                {
                    if (!string.IsNullOrEmpty(config.MqttTopic))
                    {
                        if (!usedTopics.ContainsKey(config.MqttTopic))
                        {
                            usedTopics[config.MqttTopic] = new List<string>();
                        }
                        usedTopics[config.MqttTopic].Add(config.Name.ToString());
                    }
                }
                
                // 定义允许共享主题的组合（这些不算冲突）
                var allowedSharedTopics = new Dictionary<string, HashSet<string>>
                {
                    [$"EVE/{Factory_id}/EQP/{Device_name}"] = new HashSet<string> { "Axis", "Cylinder", "ParameterUpload" }
                };
                
                foreach (var topic in usedTopics.Where(t => t.Value.Count > 1))
                {
                    // 检查是否是允许的共享主题
                    bool isAllowedSharing = false;
                    if (allowedSharedTopics.TryGetValue(topic.Key, out var allowedTypes))
                    {
                        var currentTypes = new HashSet<string>(topic.Value);
                        if (currentTypes.IsSubsetOf(allowedTypes) || allowedTypes.IsSubsetOf(currentTypes))
                        {
                            isAllowedSharing = true;
                        }
                    }
                    
                    if (!isAllowedSharing)
                    {
                        topicConflicts.Add($"主题 '{topic.Key}' 被多个类型使用: {string.Join(", ", topic.Value)}");
                    }
                }
                
                diagnostics["TopicConflicts"] = topicConflicts;
                diagnostics["CheckTimestamp"] = DateTime.Now;
                
                _mqttTopicLogger.WriteSystemInfo($"主题诊断完成: 发现 {topicConflicts.Count} 个冲突");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"主题诊断出错: {ex.Message}", ex);
                diagnostics["Error"] = ex.Message;
            }
            
            return diagnostics;
        }

        /// <summary>
        /// 系统健康检查 - 检查各个组件的状态
        /// </summary>
        /// <returns>健康检查报告</returns>
        public Dictionary<string, object> GetSystemHealthStatus()
        {
            var health = new Dictionary<string, object>();
            
            try
            {
                // PLC连接状态
                health["PLC_Connected"] = _plcWrapper?.IsConnected ?? false;
                health["PLC_Address"] = $"{PlcIpAddress}:{PlcPort}";
                
                // 数据采集任务状态
                health["DataCollection_Started"] = _dataCollectionTaskStarted;
                health["CancellationToken_Cancelled"] = _cts.IsCancellationRequested;
                
                // MQTT客户端状态
                var mqttStatus = new Dictionary<string, bool>();
                if (mqttClients != null)
                {
                    foreach (var client in mqttClients)
                    {
                        mqttStatus[client.Key] = client.Value.IsConnected;
                    }
                }
                health["MQTT_Clients"] = mqttStatus;
                
                // 客户端组状态
                var groupStatus = new Dictionary<string, object>();
                foreach (var group in _mqttClientGroups.Values)
                {
                    groupStatus[group.Name] = new
                    {
                        Enabled = group.IsEnabled,
                        HasCollectionTask = clientGroupCollectionTasks.ContainsKey(group.Name),
                        TaskCancelled = clientGroupCollectionTasks.ContainsKey(group.Name) ? 
                            clientGroupCollectionTasks[group.Name].IsCancellationRequested : false
                    };
                }
                health["ClientGroups"] = groupStatus;
                
                // 消息队列状态
                health["MessageQueue_Running"] = _mqttMessageQueue?.IsRunning ?? false;
                
                // 配置状态
                health["TypeConfigs_Count"] = _typeConfigs?.Count ?? 0;
                health["CollectionGroups_Count"] = _collectionGroups?.Count ?? 0;
                health["AcquisitionTypes_Count"] = AcqTypes?.Length ?? 0;
                
                // 时间戳
                health["Check_Timestamp"] = DateTime.Now;
                
                _mqttTopicLogger.WriteSystemInfo($"系统健康检查完成: PLC={health["PLC_Connected"]}, 采集任务={health["DataCollection_Started"]}, MQTT客户端={mqttStatus.Count}个");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"系统健康检查出错: {ex.Message}", ex);
                health["Error"] = ex.Message;
                health["Check_Timestamp"] = DateTime.Now;
            }
            
            return health;
        }

        /// <summary>
        /// 测试配置文件加载
        /// </summary>
        private void TestConfigLoading()
        {
            try
            {
                _mqttTopicLogger.WriteConfigOperation("配置测试", "开始", "开始测试配置文件加载");
                
                // 获取应用程序配置文件的路径
                string configPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
                _mqttTopicLogger.WriteConfigOperation("配置测试", "文件路径", configPath);
                
                // 检查文件是否存在
                if (!File.Exists(configPath))
                {
                    _mqttTopicLogger.WriteSystemError($"配置文件不存在: {configPath}");
                    return;
                }
                
                // 尝试打开配置文件
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                _mqttTopicLogger.WriteConfigOperation("配置测试", "文件打开", $"成功打开配置文件: {config.FilePath}");
                
                // 检查appSettings节点是否存在
                if (config.AppSettings.Settings.Count == 0)
                {
                    _mqttTopicLogger.WriteSystemError("appSettings节点为空或不存在");
                }
                else
                {
                    _mqttTopicLogger.WriteConfigOperation("配置测试", "设置节点", $"appSettings节点包含 {config.AppSettings.Settings.Count} 个配置项");
                    
                    // 输出前5个配置项
                    int count = 0;
                    foreach (var key in config.AppSettings.Settings.AllKeys)
                    {
                        if (count < 5)
                        {
                            _mqttTopicLogger.WriteConfigOperation("配置测试", "配置项", $"{key} = {config.AppSettings.Settings[key].Value}");
                            count++;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                
                // 尝试直接读取一些关键配置项
                string plcIp = ConfigurationManager.AppSettings["PlcIpAddress"];
                string mqttAddress = ConfigurationManager.AppSettings["MQTTServerAddress"];
                
                _mqttTopicLogger.WriteConfigOperation("配置测试", "直接读取", $"PlcIpAddress = {plcIp ?? "null"}");
                _mqttTopicLogger.WriteConfigOperation("配置测试", "直接读取", $"MQTTServerAddress = {mqttAddress ?? "null"}");
                
                _mqttTopicLogger.WriteConfigOperation("配置测试", "完成", "配置文件加载测试完成");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"测试配置文件加载时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 系统配置文件读取
        /// </summary>
        private void InitializeConfig()
        {
            try
            {
                _mqttTopicLogger.WriteConfigOperation("配置加载", "开始", "开始读取配置文件");
               // ReadConfigFromXml();

                // 确保配置管理器可以访问配置文件
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                _mqttTopicLogger.WriteConfigOperation("配置加载", "文件路径", config.FilePath);

                // 读取PLC配置
                PlcIpAddress = GetConfigValue("PlcIpAddress", "127.0.0.1");
                PlcPort = int.Parse(GetConfigValue("PlcPort", "9600"));
                _mqttTopicLogger.WriteConfigOperation("配置加载", "PLC配置", $"{PlcIpAddress}:{PlcPort}");

                // 读取MQTT配置
                MQTTServerAddress = GetConfigValue("MQTTServerAddress", "127.0.0.1");
                MQTTServerPort = int.Parse(GetConfigValue("MQTTServerPort", "1883"));
                _mqttTopicLogger.WriteConfigOperation("配置加载", "MQTT配置", $"{MQTTServerAddress}:{MQTTServerPort}");

                ClientId = GetConfigValue("ClientId", "601UPW01");
                
                // 读取业务配置
                BU_id = GetConfigValue("BU_id", "EVE2BU");
                District_id = GetConfigValue("District_id", "QJ");
                Factory_id = GetConfigValue("Factory_id", "60J");
                Production_line_id = GetConfigValue("Production_line_id", "MW-601");
                Work_Center_id = GetConfigValue("Work_Center_id", "601FGE02");
                production_processes_id = GetConfigValue("production_processes_id", "P020");
                // 主题配置已迁移到Config.xml动态配置中，不再从App.config读取
                DEFAULT_ROBOT_TOPIC_PREFIX = $"EVE/{Factory_id}/ROBOT/";
                // Device_name现在统一从Config.xml中读取

                // 读取其他配置
                ThreadInterval = int.Parse(GetConfigValue("ThreadInterval", "50"));
                SwitchLog = bool.Parse(GetConfigValue("SwitchLog", "True"));
                
                // 设置MqttDataService的静态属性
                MqttDataService.BU_id = BU_id;
                MqttDataService.District_id = District_id;
                MqttDataService.Factory_id = Factory_id;
                MqttDataService.Production_line_id = Production_line_id;
                // MqttDataService.Device_name将在ReadConfigFromXml中设置
                MqttDataService.Work_Center_id = Work_Center_id;

                ReadConfigFromXml();
                _mqttTopicLogger.WriteConfigOperation("配置加载", "完成", "读取系统配置文件成功！");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"读取配置文件时出错: {ex.Message}", ex);
                // 设置默认值
               // SetDefaultConfig();
            }
        }

        private string GetConfigValue(string key, string defaultValue)
        {
            try
            {
                string value = ConfigurationManager.AppSettings[key];
                if (string.IsNullOrEmpty(value))
                {
                    _mqttTopicLogger.WriteWarning("CONFIG", $"配置项 '{key}' 未找到或为空，使用默认值: {defaultValue}");
                    return defaultValue;
                }
                _mqttTopicLogger.WriteConfigOperation("配置读取", key, value);
                return value;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"读取配置项 '{key}' 时出错: {ex.Message}", ex);
                return defaultValue;
            }
        }

        private void SetDefaultConfig()
        {
            _mqttTopicLogger.WriteWarning("CONFIG", "使用默认配置值");
            
            // 设置默认PLC配置
            PlcIpAddress = "127.0.0.1";
            PlcPort = 9600;
            
            // 设置默认MQTT配置
            MQTTServerAddress = "127.0.0.1";
            MQTTServerPort = 2883;
            ClientId = "602VIM01";
            // 主题配置已迁移到Config.xml动态配置中
            
            // 设置默认业务配置
            BU_id = "EVE2BU";
            District_id = "QJ";
            Factory_id = "58M";
            Production_line_id = "MW-602";
            Work_Center_id = "602VIM01";
            // Device_name统一从Config.xml中读取，不设置默认值

            // 设置默认其他配置
            ThreadInterval = 50;
            SwitchLog = true;
            
            // 设置MqttDataService的静态属性
            MqttDataService.BU_id = BU_id;
            MqttDataService.District_id = District_id;
            MqttDataService.Factory_id = Factory_id;
            MqttDataService.Production_line_id = Production_line_id;
            // MqttDataService.Device_name将在ReadConfigFromXml中设置
            MqttDataService.Work_Center_id = Work_Center_id;
        }

        /// <summary>
        /// 根据启用设备的CollectionGroup动态创建配置
        /// </summary>
        private void ReadConfigFromXml()
        {
            try
            {
                var configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.xml");
                var doc = XDocument.Load(configPath);
                string deviceName = "";

                // 初始化字典
                _plcAddresses = new Dictionary<AcquisitionType, Dictionary<string, string>>();
                _collectionGroups = new Dictionary<AcquisitionType, CollectionGroupConfig>();
                _typeConfigs = new List<TypeConfig>();
                _acquisitionTypeConfigs = new Dictionary<AcquisitionType, AcquisitionTypeConfig>();
                _mqttClientGroups = new Dictionary<string, MqttClientGroupConfig>();

                // 查找启用的设备
                foreach (var deviceElement in doc.Descendants("Device"))
                {
                    var isEnabled = bool.Parse(deviceElement.Attribute("isEnable")?.Value ?? "False");
                    if (isEnabled)
                    {
                        deviceName = deviceElement.Attribute("name")?.Value;
                        _mqttTopicLogger.WriteConfigOperation("设备配置", "找到启用设备", deviceName);

                        // 更新全局设备名称
                        Device_name = deviceName;
                        MqttDataService.Device_name = deviceName;
                        _mqttTopicLogger.WriteConfigOperation("设备配置", "更新设备名称", Device_name);

                        // 动态创建客户端组配置
                        CreateDynamicClientGroupConfigs(deviceElement, deviceName);

                        // 读取设备下的CollectionGroup配置
                        ProcessDeviceCollectionGroups(deviceElement, deviceName);
                        
                        // 调试：打印所有配置
                        DebugPrintAllAcquisitionTypeConfigs();
                        
                        break; // 只处理第一个启用的Device
                    }
                }

                if (string.IsNullOrEmpty(deviceName))
                {
                    _mqttTopicLogger.WriteSystemError("未找到任何启用的设备配置！");
                    return;
                }

                _mqttTopicLogger.WriteConfigOperation("设备配置", "加载完成", $"读取设备【{deviceName}】配置成功，共加载 {_typeConfigs.Count} 个类型配置");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"读取配置文件错误: {ex.Message}", ex);
                _typeConfigs = new List<TypeConfig>();
            }
        }

        /// <summary>
        /// 根据设备的CollectionGroup动态创建客户端组配置
        /// </summary>
        private void CreateDynamicClientGroupConfigs(XElement deviceElement, string deviceName)
        {
            var collectionGroups = deviceElement.Elements("CollectionGroup").ToList();
            var deviceId = deviceName; // 直接使用完整设备名称作为ID，如601FIM01

            // 定义客户端组映射规则
            var clientGroupMappings = new Dictionary<string, ClientGroupMapping>
            {
                {
                    "PPM", new ClientGroupMapping
                    {
                        ClientId = $"PPM_Client_{deviceId}",
                        Description = "PPM生产性能数据专用客户端",
                        CollectionIntervalMs = 1000,
                        CollectionGroupNames = new[] { "PPM" },
                        MqttTopic = $"EVE/{Factory_id}/EQP/NEW_PPM/{deviceId}",
                        ProcessType = "PPM"
                    }
                },
                {
                    "AxisCylinder", new ClientGroupMapping
                    {
                        ClientId = $"AxisCylinder_Client_{deviceId}",
                        Description = "轴扭矩和气缸数据专用客户端",
                        CollectionIntervalMs = 1000,
                        CollectionGroupNames = new[] { "Axis", "Cylinder" },
                        MqttTopic = $"EVE/{Factory_id}/EQP/{deviceId}",
                        ProcessType = "Float"
                    }
                },
                {
                    "Robotic", new ClientGroupMapping
                    {
                        ClientId = $"Robotic_Client_{deviceId}",
                        Description = "机械臂数据专用客户端",
                        CollectionIntervalMs = 500,
                        CollectionGroupNames = new[] { "LoadingRobotic", "LoadingTransferRobotic", "DischargeTransferRobotic", "DischargeRobotic", "InternalRobotic", "UnpackingRobotic", "FullNailingRobotic", "ThicknessTransferRobotic" },
                        MqttTopic = $"EVE/{Factory_id}/ROBOT/",
                        ProcessType = "Robot"
                    }
                },
                {
                    "ParameterDown", new ClientGroupMapping
                    {
                        ClientId = $"ParameterDown_Client_{deviceId}",
                        Description = "参数下发专用客户端",
                        CollectionIntervalMs = 0,
                        CollectionGroupNames = new[] { "Parameter" },
                        MqttTopic = $"CPSET/SVDOWN/{deviceId}",
                        ProcessType = "ParameterDown"
                    }
                },
                {
                    "ParameterUpload", new ClientGroupMapping
                    {
                        ClientId = $"ParameterUp_Client_{deviceId}",
                        Description = "参数上传专用客户端",
                        CollectionIntervalMs = 1000,
                        CollectionGroupNames = new[] { "Parameter" }, // 复用Parameter的CollectionGroup
                        MqttTopic = $"EVE/{Factory_id}/EQP/{deviceId}",
                        ProcessType = "ParameterUpload"
                    }
                }
            };

            // 检查设备中存在的CollectionGroup，并创建相应的客户端组
            // 按照特定顺序处理，确保Parameter在ParameterUpload之前处理
            var orderedMappings = new[] { "PPM", "AxisCylinder", "Robotic", "ParameterDown", "ParameterUpload" }
                .Where(key => clientGroupMappings.ContainsKey(key))
                .Select(key => new KeyValuePair<string, ClientGroupMapping>(key, clientGroupMappings[key]));

            foreach (var mapping in orderedMappings)
            {
                var hasAnyGroup = mapping.Value.CollectionGroupNames.Any(groupName => 
                    collectionGroups.Any(cg => cg.Attribute("name")?.Value == groupName));

                if (hasAnyGroup)
                {
                    var existingTypes = mapping.Value.CollectionGroupNames
                        .Where(groupName => collectionGroups.Any(cg => cg.Attribute("name")?.Value == groupName))
                        .ToList();

                        var config = new MqttClientGroupConfig
                        {
                        Name = mapping.Key,
                        ClientId = mapping.Value.ClientId,
                        Description = mapping.Value.Description,
                        AcquisitionTypes = existingTypes,
                        IsEnabled = true,
                        CollectionIntervalMs = mapping.Value.CollectionIntervalMs
                        };

                        _mqttClientGroups[config.Name] = config;
                    _mqttTopicLogger.WriteConfigOperation("客户端组", "动态创建", $"{config.Name} (ClientId: {config.ClientId}, 类型: {string.Join(",", config.AcquisitionTypes)}, 采集间隔: {config.CollectionIntervalMs}ms)");

                    // 同时创建AcquisitionType配置
                    foreach (var groupName in existingTypes)
                    {
                        if (Enum.TryParse<AcquisitionType>(groupName, out var acquisitionType))
                        {
                            var isRobot = mapping.Value.ProcessType == "Robot";
                            var mqttTopic = isRobot ? "" : mapping.Value.MqttTopic; // 机器人类型topic为空，使用robotTopicPrefix
                            var robotTopicPrefix = isRobot ? mapping.Value.MqttTopic : "";

                            var acquisitionConfig = new AcquisitionTypeConfig
                            {
                                Name = acquisitionType,
                                MqttTopic = mqttTopic,
                                IsRobot = isRobot,
                                IsEnabled = true,
                                ProcessType = mapping.Value.ProcessType,
                                RobotTopicPrefix = robotTopicPrefix,
                                Priority = GetPriorityForType(acquisitionType),
                                RequiresSubscription = mapping.Key == "ParameterDown" // 只有参数下发需要订阅
                            };

                            // 避免重复创建同一个AcquisitionType的配置
                            if (!_acquisitionTypeConfigs.ContainsKey(acquisitionType))
                            {
                                _acquisitionTypeConfigs[acquisitionType] = acquisitionConfig;
                                _mqttTopicLogger.WriteConfigOperation("采集类型", "动态创建", $"{acquisitionType} -> Topic: {mqttTopic}, Robot: {isRobot}, ProcessType: {mapping.Value.ProcessType}");
                            }
                            else
                            {
                                _mqttTopicLogger.WriteConfigOperation("采集类型", "跳过重复", $"采集类型 {acquisitionType} 的配置已存在，跳过重复创建。现有ProcessType: {_acquisitionTypeConfigs[acquisitionType].ProcessType}");
                            }
                        }
                    }

                    // 特殊处理：为ParameterUpload客户端组创建ParameterUpload类型配置
                    if (mapping.Key == "ParameterUpload" && !_acquisitionTypeConfigs.ContainsKey(AcquisitionType.ParameterUpload))
                    {
                        var parameterUploadConfig = new AcquisitionTypeConfig
                        {
                            Name = AcquisitionType.ParameterUpload,
                            MqttTopic = mapping.Value.MqttTopic,
                            IsRobot = false,
                            IsEnabled = true,
                            ProcessType = mapping.Value.ProcessType,
                            RobotTopicPrefix = "",
                            Priority = GetPriorityForType(AcquisitionType.ParameterUpload),
                            RequiresSubscription = false // ParameterUpload是发布，不需要订阅
                        };

                        _acquisitionTypeConfigs[AcquisitionType.ParameterUpload] = parameterUploadConfig;
                        _mqttTopicLogger.WriteConfigOperation("采集类型", "特殊创建", $"ParameterUpload -> Topic: {mapping.Value.MqttTopic}, ProcessType: {mapping.Value.ProcessType}");
                        
                        // 同时修正ParameterUpload客户端组的AcquisitionTypes
                        if (_mqttClientGroups.TryGetValue("ParameterUpload", out var paramUploadGroup))
                        {
                            paramUploadGroup.AcquisitionTypes = new List<string> { "ParameterUpload" };
                            _mqttTopicLogger.WriteConfigOperation("客户端组", "修正", "修正ParameterUpload客户端组的AcquisitionTypes为: [ParameterUpload]");
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 调试方法：打印所有AcquisitionTypeConfig
        /// </summary>
        private void DebugPrintAllAcquisitionTypeConfigs()
        {
            _mqttTopicLogger.WriteSystemInfo("=== 所有AcquisitionTypeConfig配置 ===");
            foreach (var config in _acquisitionTypeConfigs)
            {
                _mqttTopicLogger.WriteConfigOperation("AcquisitionType配置", config.Key.ToString(), $"ProcessType: {config.Value.ProcessType}, Topic: {config.Value.MqttTopic}, IsEnabled: {config.Value.IsEnabled}");
            }
            _mqttTopicLogger.WriteSystemInfo("=== 配置结束 ===");
        }

        /// <summary>
        /// 处理设备的CollectionGroup配置
        /// </summary>
        private void ProcessDeviceCollectionGroups(XElement deviceElement, string deviceName)
        {
                        foreach (var groupElement in deviceElement.Elements("CollectionGroup"))
                        {
                            var groupName = groupElement.Attribute("name").Value;
                _mqttTopicLogger.WriteConfigOperation("寄存器组", "处理", groupName);

                if (Enum.TryParse<AcquisitionType>(groupName, out var acquisitionType))
                {
                    var startAddress = groupElement.Attribute("StartAddress")?.Value;
                    var length = int.Parse(groupElement.Attribute("length")?.Value ?? "100");
                    var robotName = groupElement.Attribute("RobotName")?.Value;

                            var groupConfig = new CollectionGroupConfig
                            {
                                Name = groupName,
                        StartAddress = startAddress,
                        Length = length,
                        RobotName = robotName,
                                Types = new Dictionary<string, TypeConfig>()
                            };

                            var groupAddresses = new Dictionary<string, string>();

                            foreach (var typeElement in groupElement.Elements("Type"))
                            {
                        var typeName = typeElement.Attribute("name")?.Value;
                        var typeAddress = typeElement.Attribute("address")?.Value;
                        var dataTypeStr = typeElement.Attribute("DataType")?.Value ?? "Float";
                        
                        if (Enum.TryParse<PLCDataType>(dataTypeStr, out var dataType))
                        {
                                var typeConfig = new TypeConfig
                                {
                                    Name = typeName,
                                    Address = typeAddress,
                                DataType = dataType.ToString(),
                                GroupName = groupName
                                };

                                groupConfig.Types[typeName] = typeConfig;
                                groupAddresses[typeName] = typeAddress;
                            _typeConfigs.Add(typeConfig);

                                _mqttTopicLogger.WriteConfigOperation("类型添加", typeName, $"地址: {typeAddress}, 数据类型: {dataType}");
                        }
                        else
                        {
                            _mqttTopicLogger.WriteSystemError($"无法解析数据类型: {dataTypeStr} for {typeName}");
                        }
                            }

                            _collectionGroups[acquisitionType] = groupConfig;
                            _plcAddresses[acquisitionType] = groupAddresses;
                        }
                else
                {
                    _mqttTopicLogger.WriteSystemError($"无法解析采集类型: {groupName}");
                }
            }
        }

        /// <summary>
        /// 获取采集类型的优先级
        /// </summary>
        private int GetPriorityForType(AcquisitionType type)
        {
            switch (type)
            {
                case AcquisitionType.PPM: return 1;
                case AcquisitionType.Axis: return 2;
                case AcquisitionType.Cylinder: return 3;
                case AcquisitionType.LoadingRobotic: return 4;
                case AcquisitionType.LoadingTransferRobotic: return 5;
                case AcquisitionType.DischargeTransferRobotic: return 6;
                case AcquisitionType.DischargeRobotic: return 7;
                case AcquisitionType.InternalRobotic: return 8;
                case AcquisitionType.UnpackingRobotic: return 9;
                case AcquisitionType.FullNailingRobotic: return 10;
                case AcquisitionType.ThicknessTransferRobotic: return 11;
                case AcquisitionType.ParameterDownload: return 12;
                case AcquisitionType.ParameterUpload: return 13;
                case AcquisitionType.Parameter: return 14;
                default: return 99;
            }
        }


        #region 初始化Task线程，PLC，MQTT
        private void InitializeTask()
        {
            if (_collectionGroups != null && _collectionGroups.Count > 0)
            {
                List<AcquisitionType> typesList = new List<AcquisitionType>();
                
                // 基于配置动态选择启用的采集类型
                foreach (var kvp in _collectionGroups)
                {
                    if (_acquisitionTypeConfigs.TryGetValue(kvp.Key, out var config))
                    {
                        // 只添加配置中启用的类型
                        if (config.IsEnabled)
                        {
                            typesList.Add(kvp.Key);
                            _mqttTopicLogger.WriteConfigOperation("采集类型", "启用", $"{config.Name}, 优先级: {config.Priority}");
                        }
                        else
                        {
                            _mqttTopicLogger.WriteConfigOperation("采集类型", "跳过", $"禁用的采集类型: {config.Name}");
                        }
                    }
                    else
                    {
                        // 如果没有配置，默认启用（保持向后兼容）
                            typesList.Add(kvp.Key);
                        _mqttTopicLogger.WriteConfigOperation("采集类型", "默认启用", $"采集类型 {kvp.Key} 没有配置，默认启用");
                    }
                }

                // 按优先级排序
                typesList = typesList.OrderBy(type => 
                    _acquisitionTypeConfigs.TryGetValue(type, out var config) ? config.Priority : 0
                ).ToList();

                // 将 List 转换为数组
                AcqTypes = typesList.ToArray();

                if (AcqTypes.Length > 0)
                {
                    _mqttTopicLogger.WriteConfigOperation("采集类型", "汇总", "已启用的采集类型: " + string.Join(", ", AcqTypes));
                }
                else
                {
                    _mqttTopicLogger.WriteSystemError("没有启用的采集类型！");
                }
            }
        }




        private async void InitializePLC()
        {
            try
            {
                _mqttTopicLogger.WriteServiceStatus("PLC连接", "初始化中", "开始初始化PLC连接");
                bool connected = await _plcWrapper.ConnectAsync();
                if (connected)
                {
                    _mqttTopicLogger.WriteServiceStatus("PLC连接", "成功", "PLC初始化并连接成功");
                }
                else
                {
                    _mqttTopicLogger.WriteServiceStatus("PLC连接", "失败", "PLC初始连接失败，将启动后台重连任务");
                }
                    
                // 无论PLC是否连接成功，都启动数据采集任务
                // 数据采集任务内部会处理PLC未连接的情况并自动重连
                    await StartDataCollectionTask();
                
                // 启动独立的PLC连接监控任务
                _ = Task.Run(async () => await StartPLCConnectionMonitorTask(_cts.Token));
                
                _mqttTopicLogger.WriteServiceStatus("PLC连接", "初始化完成", "PLC初始化流程完成，数据采集任务已启动");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"初始化 PLC 错误: {ex.Message}", ex);
                // 即使出错也要启动数据采集任务，让其自行处理重连
                try
                {
                    await StartDataCollectionTask();
                    _mqttTopicLogger.WriteServiceStatus("数据采集任务", "已启动", "数据采集任务已启动，将自动处理PLC重连");
                }
                catch (Exception startEx)
                {
                    _mqttTopicLogger.WriteSystemError($"启动数据采集任务失败: {startEx.Message}", startEx);
                }
            }
        }

        /// <summary>
        /// 启动PLC连接监控任务 - 独立的后台重连任务
        /// </summary>
        /// <param name="ct">取消令牌</param>
        /// <returns></returns>
        private async Task StartPLCConnectionMonitorTask(CancellationToken ct)
        {
            _mqttTopicLogger.WriteServiceStatus("PLC监控任务", "启动", "PLC连接监控任务开始运行");
            
            while (!ct.IsCancellationRequested)
            {
                try
                {
                    // 检查PLC连接状态
                    if (_plcWrapper == null)
                    {
                        _mqttTopicLogger.WriteWarning("PLC", "PLC监控任务: PLC包装器为空，等待初始化");
                        await Task.Delay(10000, ct); // 等待10秒
                        continue;
                    }

                    if (!_plcWrapper.IsConnected)
                    {
                        _mqttTopicLogger.WriteServiceStatus("PLC监控任务", "重连中", "检测到PLC未连接，开始自动重连");
                        
                        // 尝试重连
                        bool reconnected = await AttemptReconnection(ct);
                        if (reconnected)
                        {
                            _mqttTopicLogger.WriteServiceStatus("PLC监控任务", "重连成功", "PLC监控任务: 自动重连成功");
                            
                            // 确保数据采集任务已启动
                            if (!_dataCollectionTaskStarted)
                            {
                                _mqttTopicLogger.WriteServiceStatus("PLC监控任务", "启动采集", "检测到数据采集任务未启动，准备启动");
                                await StartDataCollectionTask();
                            }
                }
                else
                {
                            _mqttTopicLogger.WriteServiceStatus("PLC监控任务", "重连失败", "自动重连失败，将在30秒后重试");
                            await Task.Delay(30000, ct); // 重连失败时等待30秒
                            continue;
                        }
                    }
                    
                    // PLC连接正常时，每60秒检查一次
                    await Task.Delay(60000, ct);
                }
                catch (OperationCanceledException)
                {
                    _mqttTopicLogger.WriteServiceStatus("PLC监控任务", "正常取消", "PLC连接监控任务被正常取消");
                    break;
            }
            catch (Exception ex)
            {
                    _mqttTopicLogger.WriteSystemError($"PLC连接监控任务错误: {ex.Message}", ex);
                    await Task.Delay(5000, ct); // 出错时等待5秒
            }
            }
            
            _mqttTopicLogger.WriteServiceStatus("PLC监控任务", "已停止", "PLC连接监控任务已停止");
        }

        /// <summary>
        /// 启动数据采集任务
        /// </summary>
        private async Task StartDataCollectionTask()
        {
            try
            {
                if (_dataCollectionTaskStarted)
                {
                    _mqttTopicLogger.WriteServiceStatus("数据采集任务", "已运行", "数据采集任务已经在运行，跳过重复启动");
                    return;
                }

                _mqttTopicLogger.WriteServiceStatus("数据采集任务", "启动中", "启动多客户端组数据采集任务");
                
                // 为每个客户端组启动独立的采集任务
                StartClientGroupCollectionTasks();
                
                _dataCollectionTaskStarted = true;
                _mqttTopicLogger.WriteServiceStatus("数据采集任务", "启动成功", "多客户端组数据采集任务启动成功");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"启动数据采集任务时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 为每个客户端组启动独立的采集任务
        /// </summary>
        private void StartClientGroupCollectionTasks()
        {
            foreach (var clientGroup in _mqttClientGroups.Values)
            {
                if (!clientGroup.IsEnabled)
                {
                    _mqttTopicLogger.WriteServiceStatus("客户端组", "跳过", $"禁用的客户端组: {clientGroup.Name}");
                    continue;
                }

                // Parameter客户端组不需要数据采集任务（只处理参数下发）
                if (clientGroup.Name == "ParameterDown")
                {
                    _mqttTopicLogger.WriteServiceStatus("客户端组", "跳过", "ParameterDown客户端组不需要数据采集任务");
                    continue;
                }

                // ParameterUpload客户端组需要特殊的定时上传任务
                if (clientGroup.Name == "ParameterUpload")
                {
                    _mqttTopicLogger.WriteServiceStatus("ParameterUpload", "启动", $"启动ParameterUpload客户端组的定时上传任务，上传间隔: {clientGroup.CollectionIntervalMs}ms");
                    
                    var cts1 = new CancellationTokenSource();
                    clientGroupCollectionTasks[clientGroup.Name] = cts1;
                    
                    Task.Run(() => RunParameterUploadTaskAsync(clientGroup, cts1.Token));
                    continue;
                }

                // 获取该客户端组负责的采集类型
                var groupAcquisitionTypes = new List<AcquisitionType>();
                foreach (var typeName in clientGroup.AcquisitionTypes)
                {
                    if (Enum.TryParse<AcquisitionType>(typeName, out var type))
                    {
                        groupAcquisitionTypes.Add(type);
                    }
                }

                if (groupAcquisitionTypes.Count == 0)
                {
                    _mqttTopicLogger.WriteServiceStatus("客户端组", "无效", $"客户端组 {clientGroup.Name} 没有有效的采集类型");
                    continue;
                }

                // 为该客户端组创建独立的采集任务
                var cts = new CancellationTokenSource();
                clientGroupCollectionTasks[clientGroup.Name] = cts;

                _mqttTopicLogger.WriteServiceStatus("数据采集任务", "启动", $"客户端组 {clientGroup.Name} 的数据采集任务，采集间隔: {clientGroup.CollectionIntervalMs}ms, 采集类型: [{string.Join(", ", groupAcquisitionTypes)}]");
                
                Task.Run(() => RunClientGroupCollectionAsync(clientGroup, groupAcquisitionTypes.ToArray(), cts.Token));
            }
        }

        /// <summary>
        /// 参数上传专用定时任务
        /// </summary>
        private async Task RunParameterUploadTaskAsync(MqttClientGroupConfig clientGroup, CancellationToken ct)
        {
            _mqttTopicLogger.WriteServiceStatus("ParameterUpload", "定时任务", $"[{clientGroup.Name}] 参数上传定时任务开始运行，上传间隔: {clientGroup.CollectionIntervalMs}ms");
            
            while (!ct.IsCancellationRequested)
            {
                try
                {
                    // 检查PLC连接状态
                    if (_plcWrapper == null || !_plcWrapper.IsConnected)
                    {
                        _mqttTopicLogger.WriteWarning("PLC", $"[{clientGroup.Name}] PLC未连接，跳过本次参数上传");
                        await Task.Delay(clientGroup.CollectionIntervalMs, ct);
                        continue;
                    }

                    // 执行参数上传
                    _mqttTopicLogger.WriteTopicLog($"EVE/{Factory_id}/EQP/P_{Device_name}", $"[{clientGroup.Name}] 开始定时参数上传", "INFO");
                    UploadParametersToIOT();
                    
                    // 等待下一次上传
                    await Task.Delay(clientGroup.CollectionIntervalMs, ct);
                }
                catch (OperationCanceledException)
                {
                    _mqttTopicLogger.WriteServiceStatus("ParameterUpload", "正常取消", $"[{clientGroup.Name}] 参数上传任务被正常取消");
                    break;
                }
                catch (Exception ex)
                {
                    _mqttTopicLogger.WriteSystemError($"[{clientGroup.Name}] 参数上传任务错误: {ex.Message}", ex);
                    // 发生错误时等待更长时间再重试
                    await Task.Delay(5000, ct);
                }
            }
            
            _mqttTopicLogger.WriteServiceStatus("ParameterUpload", "已停止", $"[{clientGroup.Name}] 参数上传任务已停止");
        }

        /// <summary>
        /// 客户端组专用采集任务
        /// </summary>
        private async Task RunClientGroupCollectionAsync(MqttClientGroupConfig clientGroup, AcquisitionType[] types, CancellationToken ct)
        {
            _mqttTopicLogger.WriteServiceStatus("数据采集任务", "开始运行", $"[{clientGroup.Name}] 数据采集任务开始运行，采集间隔: {clientGroup.CollectionIntervalMs}ms");
            
            while (!ct.IsCancellationRequested)
            {
                try
                {
                    // 检查PLC连接状态
                    if (_plcWrapper == null)
                    {
                        _mqttTopicLogger.WriteWarning("PLC", $"[{clientGroup.Name}] PLC包装器为空，等待重新初始化");
                        await Task.Delay(5000, ct);
                        continue;
                    }

                    if (!_plcWrapper.IsConnected)
                    {
                        _mqttTopicLogger.WriteServiceStatus("PLC快速重连", "尝试", $"[{clientGroup.Name}] PLC未连接，尝试快速重连");
                        
                        // 尝试快速重连（减少重试次数，避免阻塞太久）
                        bool quickReconnected = await AttemptQuickReconnection(ct);
                        if (!quickReconnected)
                        {
                            _mqttTopicLogger.WriteServiceStatus("PLC快速重连", "失败", $"[{clientGroup.Name}] 快速重连失败，等待后台监控任务处理，继续采集循环");
                        await Task.Delay(2000, ct);
                        continue;
                        }
                        else
                        {
                            _mqttTopicLogger.WriteServiceStatus("PLC快速重连", "成功", $"[{clientGroup.Name}] 快速重连成功，继续数据采集");
                        }
                    }

                    // 执行该客户端组的数据采集
                    await CollectAndPublishData($"ClientGroup_{clientGroup.Name}", types);
                    
                    // 使用该客户端组的采集间隔
                    if (clientGroup.CollectionIntervalMs > 0)
                    {
                        await Task.Delay(clientGroup.CollectionIntervalMs, ct);
                    }
                }
                catch (OperationCanceledException)
                {
                    _mqttTopicLogger.WriteServiceStatus("数据采集任务", "正常取消", $"[{clientGroup.Name}] 数据采集任务被正常取消");
                    break;
                }
                catch (Exception ex)
                {
                    _mqttTopicLogger.WriteSystemError($"[{clientGroup.Name}] 数据采集循环错误: {ex.Message}", ex);
                    // 发生错误时等待更长时间再重试
                    await Task.Delay(5000, ct);
                }
            }
            
            _mqttTopicLogger.WriteServiceStatus("数据采集任务", "已停止", $"[{clientGroup.Name}] 数据采集任务已停止");
        }

        private async void InitializeMQTT()
        {
            try
            {
                // 保留原有单一客户端用于向后兼容
                mqttClient = new MqttClientWrapper(MQTTServerAddress, MQTTServerPort, ClientId, credentials);
                
                // 初始化多个MQTT客户端组
                await InitializeMultiMqttClients();
                
                // 无论是否有客户端组，都连接默认客户端以确保向后兼容
                await mqttClient.InitializeAndConnectAsync();
                
                if (mqttClients.Count > 0)
                {
                    _mqttTopicLogger.WriteServiceStatus("MQTT初始化", "成功", $"已初始化 {mqttClients.Count} 个MQTT客户端组，同时保持默认客户端连接");
                }
                else
                {
                    _mqttTopicLogger.WriteServiceStatus("MQTT初始化", "单一模式", "使用单一MQTT客户端模式");
                }
                
                // 订阅全局默认主题（如果没有在Config.xml中配置，则使用App.config中的默认值）
                var globalTopicsSubscribed = new HashSet<string>();
                
                // 订阅从App.config读取的默认主题（向后兼容）
                //if (!string.IsNullOrEmpty(Topic))
                //{
                //    SubscribeTopic(Topic);
                //    globalTopicsSubscribed.Add(Topic);
                //    _mqttTopicLogger.WriteTopicLog(Topic, "订阅默认PPM主题 (来自App.config)", "INFO");
                //}
                //if (!string.IsNullOrEmpty(Topic1))
                //{
                //    SubscribeTopic(Topic1);
                //    globalTopicsSubscribed.Add(Topic1);
                //    _mqttTopicLogger.WriteTopicLog(Topic1, "订阅默认预测性维护主题 (来自App.config)", "INFO");
                //}

                // 基于配置动态订阅主题
                foreach (var groupConfig in _collectionGroups)
                {
                    if (_acquisitionTypeConfigs.TryGetValue(groupConfig.Key, out var typeConfig))
                    {
                        // 只处理启用的类型
                        if (!typeConfig.IsEnabled)
                        {
                            _mqttTopicLogger.WriteServiceStatus("主题订阅", "跳过", $"禁用类型 {typeConfig.Name} 的主题订阅");
                            continue;
                        }

                        // 检查是否需要订阅主题
                        if (typeConfig.RequiresSubscription && !string.IsNullOrEmpty(typeConfig.MqttTopic))
                        {
                            if (!globalTopicsSubscribed.Contains(typeConfig.MqttTopic))
                            {
                                SubscribeTopic(typeConfig.MqttTopic);
                                globalTopicsSubscribed.Add(typeConfig.MqttTopic);
                                _mqttTopicLogger.WriteTopicLog(typeConfig.MqttTopic, $"订阅配置主题 (来自Config.xml) - 类型: {typeConfig.Name}", "INFO");
                            }
                            else
                            {
                                _mqttTopicLogger.WriteTopicLog(typeConfig.MqttTopic, "主题已订阅，跳过重复订阅", "INFO");
                            }
                        }

                        // 处理机械臂类型的特殊订阅
                        if (typeConfig.IsRobot)
                        {
                            string robotTopicPrefix = !string.IsNullOrEmpty(typeConfig.RobotTopicPrefix) 
                                ? typeConfig.RobotTopicPrefix 
                                : DEFAULT_ROBOT_TOPIC_PREFIX;
                            string robotTopic = $"{robotTopicPrefix}{groupConfig.Value.RobotName}";
                            
                            if (!globalTopicsSubscribed.Contains(robotTopic))
                            {
                        SubscribeTopic(robotTopic);
                                globalTopicsSubscribed.Add(robotTopic);
                                _mqttTopicLogger.WriteTopicLog(robotTopic, $"订阅机械臂主题 - 类型: {typeConfig.Name}", "INFO");
                            }
                            else
                            {
                                _mqttTopicLogger.WriteTopicLog(robotTopic, "机械臂主题已订阅，跳过重复订阅", "INFO");
                            }
                        }
                    }
                    else
                    {
                        // 向后兼容：如果没有配置，使用原有逻辑
                        _mqttTopicLogger.WriteConfigOperation("类型配置", "默认逻辑", $"类型 {groupConfig.Key} 没有配置，使用默认逻辑");
                    }
                }

                // 订阅参数下发主题（服务端命令下发）
                string parameterDownloadTopic = $"CPSET/SVDOWN/{Device_name}";
                if (!globalTopicsSubscribed.Contains(parameterDownloadTopic))
                {
                    SubscribeTopic(parameterDownloadTopic);
                    globalTopicsSubscribed.Add(parameterDownloadTopic);
                    _mqttTopicLogger.WriteTopicLog(parameterDownloadTopic, "订阅参数下发主题", "INFO");
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"连接 MQTT 代理时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 初始化多个MQTT客户端
        /// </summary>
        private async Task InitializeMultiMqttClients()
        {
            try
            {
                _mqttTopicLogger.WriteServiceStatus("MQTT初始化", "开始", "开始初始化多MQTT客户端架构");

                foreach (var clientGroup in _mqttClientGroups.Values)
                {
                    if (!clientGroup.IsEnabled)
                    {
                        _mqttTopicLogger.WriteServiceStatus("客户端组", "跳过", $"禁用的客户端组: {clientGroup.Name}");
                        continue;
                    }

                    _mqttTopicLogger.WriteServiceStatus("MQTT客户端组", "初始化", $"初始化MQTT客户端组: {clientGroup.Name} (ClientId: {clientGroup.ClientId})");

                    // 为每个客户端组创建独立的MQTT客户端
                    var client = new MqttClientWrapper(MQTTServerAddress, MQTTServerPort, clientGroup.ClientId, credentials);
                    await client.InitializeAndConnectAsync();

                    // 检查MQTT连接状态
                    if (!client.IsConnected)
                    {
                        _mqttTopicLogger.WriteSystemError($"MQTT客户端组 {clientGroup.Name} 连接失败，跳过主题订阅");
                        continue;
                    }

                    // 为该客户端创建独立的消息队列
                    var messageQueue = new MqttMessageQueue(
                        ThreadInterval, // 使用配置的发送间隔
                        async (source, topic, type, messageJson) => await client.SendMessageAsync(source, topic, type, messageJson)
                    );
                    clientMessageQueues[client] = messageQueue;

                    // 为该客户端组订阅相关主题（确保连接成功后再订阅）
                    await SubscribeTopicsForClientGroup(client, clientGroup);

                    mqttClients[clientGroup.Name] = client;
                    _mqttTopicLogger.WriteServiceStatus("MQTT客户端组", "初始化完成", $"MQTT客户端组 {clientGroup.Name} 初始化完成");
                }

                _mqttTopicLogger.WriteServiceStatus("MQTT初始化", "完成", $"多MQTT客户端架构初始化完成，共 {mqttClients.Count} 个客户端组");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"初始化多MQTT客户端时出错: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 为客户端组订阅相关主题
        /// </summary>
        private async Task SubscribeTopicsForClientGroup(MqttClientWrapper client, MqttClientGroupConfig clientGroup)
        {
            try
            {
                var subscribedTopics = new HashSet<string>();

                foreach (var acquisitionTypeName in clientGroup.AcquisitionTypes)
                {
                    // 处理参数下发特殊情况
                    if (acquisitionTypeName == "ParameterDownload")
                    {
                        string parameterTopic = $"CPSET/SVDOWN/{Device_name}";
                        if (!subscribedTopics.Contains(parameterTopic))
                        {
                            SubscribeTopicForClient(client, parameterTopic, clientGroup.Name);
                            subscribedTopics.Add(parameterTopic);
                            _mqttTopicLogger.WriteTopicLog(parameterTopic, $"客户端组 {clientGroup.Name} 订阅参数下发主题", "INFO");
                        }
                        continue;
                    }

                    // 处理普通采集类型
                    if (Enum.TryParse<AcquisitionType>(acquisitionTypeName, out var acquisitionType))
                    {
                        if (_acquisitionTypeConfigs.TryGetValue(acquisitionType, out var typeConfig))
                        {
                            if (!typeConfig.IsEnabled)
                            {
                                _mqttTopicLogger.WriteServiceStatus("主题订阅", "跳过", $"禁用类型 {acquisitionTypeName} 的主题订阅");
                                continue;
                            }

                            // 订阅常规MQTT主题
                            if (typeConfig.RequiresSubscription && !string.IsNullOrEmpty(typeConfig.MqttTopic))
                            {
                                if (!subscribedTopics.Contains(typeConfig.MqttTopic))
                                {
                                    SubscribeTopicForClient(client, typeConfig.MqttTopic, clientGroup.Name);
                                    subscribedTopics.Add(typeConfig.MqttTopic);
                                    _mqttTopicLogger.WriteTopicLog(typeConfig.MqttTopic, $"客户端组 {clientGroup.Name} 订阅主题 - 类型: {acquisitionTypeName}", "INFO");
                                }
                            }

                            // 订阅机械臂主题
                            if (typeConfig.IsRobot && !string.IsNullOrEmpty(typeConfig.RobotTopicPrefix))
                            {
                                // 根据CollectionGroup配置中的RobotName构建具体的机械臂主题
                                if (_collectionGroups.TryGetValue(acquisitionType, out var collectionGroup) && 
                                    !string.IsNullOrEmpty(collectionGroup.RobotName))
                                {
                                    string robotTopic = $"{typeConfig.RobotTopicPrefix}{collectionGroup.RobotName}";
                                    if (!subscribedTopics.Contains(robotTopic))
                                    {
                                        SubscribeTopicForClient(client, robotTopic, clientGroup.Name);
                                        subscribedTopics.Add(robotTopic);
                                        _mqttTopicLogger.WriteTopicLog(robotTopic, $"客户端组 {clientGroup.Name} 订阅机械臂主题 - 类型: {acquisitionTypeName}, 机械臂: {collectionGroup.RobotName}", "INFO");
                                    }
                                }
                                else
                                {
                                    _mqttTopicLogger.WriteSystemError($"机械臂类型 {acquisitionTypeName} 缺少 RobotName 配置，跳过主题订阅");
                                }
                            }
                        }
                    }
                    else
                    {
                        _mqttTopicLogger.WriteSystemError($"无法解析采集类型: {acquisitionTypeName}");
                    }
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"为客户端组 {clientGroup.Name} 订阅主题时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 为特定客户端订阅主题
        /// </summary>
        private void SubscribeTopicForClient(MqttClientWrapper client, string topic, string clientGroupName)
        {
            try
            {
                // 检查客户端连接状态
                if (client == null || !client.IsConnected)
                {
                    _mqttTopicLogger.WriteSystemError($"客户端组 {clientGroupName} 未连接或为空，无法订阅主题: {topic}");
                    return;
                }

                client.OnMessageReceived += (timestamp, receivedTopic, message) =>
                {
                    try
                    {
                        // 处理接收到的MQTT消息，标记来源客户端组
                        HandleReceivedMessageFromClient(Convert.ToDateTime(timestamp), receivedTopic, message, clientGroupName);
                    }
                    catch (Exception ex)
                    {
                        _mqttTopicLogger.WriteSystemError($"客户端组 {clientGroupName} 处理接收到的MQTT消息时出错: {ex.Message}", ex);
                    }
                };
                
                client.SubscribeMessage(topic, MqttClientWrapper.MessageFormat.Json, true);
                _mqttTopicLogger.WriteTopicLog(topic, $"客户端组 {clientGroupName} 成功订阅主题", "INFO");
                _mqttTopicLogger.WriteProcessLog(topic, $"客户端组 {clientGroupName} 成功订阅主题", "TOPIC_SUBSCRIBE");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteErrorLog(topic, $"客户端组 {clientGroupName} 订阅主题时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 处理来自特定客户端的消息
        /// </summary>
        private void HandleReceivedMessageFromClient(DateTime timestamp, string topic, string message, string clientGroupName)
        {
            try
            {
                // 记录MQTT主题接收日志
                _mqttTopicLogger.WriteMessageReceived(topic, message, clientGroupName);
                
                _mqttTopicLogger.WriteTopicLog(topic, $"客户端组 {clientGroupName} 接收到MQTT消息 - 时间戳: {timestamp}", "INFO");
                
                // 创建接收消息对象，添加客户端组信息
                var receivedMessage = new ReceivedMqttMessage
                {
                    Timestamp = timestamp,
                    Topic = topic,
                    Message = message,
                    Source = $"ClientGroup_{clientGroupName}",
                    MessageType = DetermineMessageType(topic)
                };

                // 记录消息类型分析日志
                _mqttTopicLogger.WriteProcessLog(topic, $"消息分类为 {receivedMessage.MessageType?.ToString() ?? "Unknown"} 类型", "MESSAGE_TYPE");

                // 存储到全局消息列表（保持向后兼容）
                lock (_receivedMessagesLock)
                {
                    _receivedMessages.Add(receivedMessage);
                    if (_receivedMessages.Count > 100)
                    {
                        _receivedMessages.RemoveAt(0);
                    }
                }

                // 存储到客户端组专用消息列表
                lock (_clientGroupMessagesLock)
                {
                    if (!clientGroupMessages.ContainsKey(clientGroupName))
                    {
                        clientGroupMessages[clientGroupName] = new List<ReceivedMqttMessage>();
                    }

                    clientGroupMessages[clientGroupName].Add(receivedMessage);
                    if (clientGroupMessages[clientGroupName].Count > 50) // 每个客户端组保留50条消息
                    {
                        clientGroupMessages[clientGroupName].RemoveAt(0);
                    }
                }

                // 触发外部事件
                OnMqttMessageReceived?.Invoke(receivedMessage);

                // 根据客户端组分发到专用的处理方法
                ProcessMessageByClientGroup(receivedMessage, clientGroupName);
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"处理来自客户端组 {clientGroupName} 的消息时出错: {ex.Message}", ex);
                _mqttTopicLogger.WriteErrorLog(topic, $"处理消息时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 根据采集类型获取对应的MQTT客户端
        /// </summary>
        private MqttClientWrapper GetMqttClientForAcquisitionType(AcquisitionType acquisitionType)
        {
            try
            {
                string acquisitionTypeName = acquisitionType.ToString();

                foreach (var clientGroup in _mqttClientGroups.Values)
                {
                    if (clientGroup.AcquisitionTypes.Contains(acquisitionTypeName))
                    {
                        if (mqttClients.TryGetValue(clientGroup.Name, out var client))
                        {
                            _mqttTopicLogger.WriteServiceStatus("数据发送", "客户端组", $"使用客户端组 {clientGroup.Name} 发送 {acquisitionTypeName} 数据");
                            return client;
                        }
                    }
                }

                // 如果没找到对应的客户端组，使用默认客户端
                _mqttTopicLogger.WriteServiceStatus("数据发送", "默认客户端", $"未找到 {acquisitionTypeName} 对应的客户端组，使用默认客户端");
                return mqttClient;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"获取采集类型 {acquisitionType} 对应的MQTT客户端时出错: {ex.Message}", ex);
                return mqttClient; // 降级到默认客户端
            }
        }

        /// <summary>
        /// 根据消息类型获取对应的MQTT客户端（用于参数下发等特殊消息）
        /// </summary>
        private MqttClientWrapper GetMqttClientForMessageType(string messageType)
        {
            try
            {
                foreach (var clientGroup in _mqttClientGroups.Values)
                {
                    if (clientGroup.AcquisitionTypes.Contains(messageType))
                    {
                        if (mqttClients.TryGetValue(clientGroup.Name, out var client))
                        {
                            _mqttTopicLogger.WriteServiceStatus("消息发送", "客户端组", $"使用客户端组 {clientGroup.Name} 发送 {messageType} 消息");
                            return client;
                        }
                    }
                }

                _mqttTopicLogger.WriteServiceStatus("消息发送", "默认客户端", $"未找到 {messageType} 对应的客户端组，使用默认客户端");
                return mqttClient;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"获取消息类型 {messageType} 对应的MQTT客户端时出错: {ex.Message}", ex);
                return mqttClient;
            }
        }

        /// <summary>
        /// 根据客户端组分发消息到专用处理方法
        /// </summary>
        private void ProcessMessageByClientGroup(ReceivedMqttMessage receivedMessage, string clientGroupName)
        {
            try
            {
                _mqttTopicLogger.WriteServiceStatus("消息处理", "开始", $"客户端组 {clientGroupName} 开始专用消息处理");

                switch (clientGroupName.ToUpper())
                {
                    case "PPM":
                        ProcessPPMClientMessages(receivedMessage);
                        break;

                    case "AXISCYLINDER":
                        ProcessAxisCylinderClientMessages(receivedMessage);
                        break;

                    case "ROBOTIC":
                        ProcessRoboticClientMessages(receivedMessage);
                        break;

                    case "PARAMETERDOWN":
                        ProcessParameterClientMessages(receivedMessage);
                        break;

                    case "PARAMETERUPLOAD":
                        ProcessParameterUploadClientMessages(receivedMessage);
                        break;

                    default:
                        _mqttTopicLogger.WriteWarning("消息处理", $"未知的客户端组: {clientGroupName}，使用通用处理方法");
                        ProcessReceivedMessage(receivedMessage);
                        break;
                }

                // 标记消息已处理
                receivedMessage.IsProcessed = true;
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, $"客户端组 {clientGroupName} 消息处理完成", "INFO");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"客户端组 {clientGroupName} 处理消息时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// PPM客户端专用消息处理
        /// </summary>
        private void ProcessPPMClientMessages(ReceivedMqttMessage receivedMessage)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[PPM客户端] 处理消息", "INFO");

                // PPM客户端通常处理生产性能相关的反馈消息
                if (!IsValidJson(receivedMessage.Message))
                {
                    _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[PPM客户端] 消息格式不是有效的JSON", new FormatException($"无效JSON: {receivedMessage.Message}"));
                    return;
                }

                try
                {
                    var ppmData = JsonConvert.DeserializeObject<dynamic>(receivedMessage.Message);
                    
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[PPM客户端] 接收到PPM反馈数据", "INFO");
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, $"[PPM客户端] 消息内容: {receivedMessage.Message}", "INFO");
                    
                    // TODO: 实现PPM特定的业务逻辑
                    // 比如：生产性能数据确认、质量反馈处理等
                    
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[PPM客户端] PPM消息处理完成", "INFO");
                }
                catch (JsonException ex)
                {
                    _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[PPM客户端] JSON解析失败", ex);
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[PPM客户端] 处理消息时出错", ex);
            }
        }

        /// <summary>
        /// AxisCylinder客户端专用消息处理
        /// </summary>
        private void ProcessAxisCylinderClientMessages(ReceivedMqttMessage receivedMessage)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[AxisCylinder客户端] 处理消息", "INFO");

                // AxisCylinder客户端处理轴扭矩和气缸相关的反馈消息
                if (!IsValidJson(receivedMessage.Message))
                {
                    _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[AxisCylinder客户端] 消息格式不是有效的JSON", new FormatException($"无效JSON: {receivedMessage.Message}"));
                    return;
                }

                try
                {
                    var axisData = JsonConvert.DeserializeObject<dynamic>(receivedMessage.Message);
                    
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[AxisCylinder客户端] 接收到轴扭矩/气缸反馈数据", "INFO");
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, $"[AxisCylinder客户端] 消息内容: {receivedMessage.Message}", "INFO");
                    
                    // TODO: 实现AxisCylinder特定的业务逻辑
                    // 比如：扭矩调整确认、气缸动作反馈处理等
                    
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[AxisCylinder客户端] AxisCylinder消息处理完成", "INFO");
                }
                catch (JsonException ex)
                {
                    _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[AxisCylinder客户端] JSON解析失败", ex);
                }
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[AxisCylinder客户端] 处理消息时出错", ex);
            }
        }

        /// <summary>
        /// Robotic客户端专用消息处理
        /// </summary>
        private void ProcessRoboticClientMessages(ReceivedMqttMessage receivedMessage)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[Robotic客户端] 处理消息", "INFO");

                // Robotic客户端处理机械臂相关的反馈消息
                if (!IsValidJson(receivedMessage.Message))
                {
                     _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[Robotic客户端] 消息格式不是有效的JSON", new FormatException($"无效JSON: {receivedMessage.Message}"));
                    return;
                }

                try
                {
                    var robotData = JsonConvert.DeserializeObject<dynamic>(receivedMessage.Message);
                    
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[Robotic客户端] 接收到机械臂反馈数据", "INFO");
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, $"[Robotic客户端] 消息内容: {receivedMessage.Message}", "INFO");
                    
                    // TODO: 实现Robotic特定的业务逻辑
                    // 比如：机械臂动作确认、位置反馈、状态更新等
                    
                    // 可以根据主题进一步区分不同的机械臂
                    if (receivedMessage.Topic.Contains("LoadingRobotic"))
                    {
                        _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[Robotic客户端] 处理装载机械臂反馈", "INFO");
                    }
                    else if (receivedMessage.Topic.Contains("DischargeRobotic"))
                    {
                        _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[Robotic客户端] 处理卸载机械臂反馈", "INFO");
                    }
                    
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[Robotic客户端] Robotic消息处理完成", "INFO");
                }
                catch (JsonException ex)
                {
                     _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[Robotic客户端] JSON解析失败", ex);
                }
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[Robotic客户端] 处理消息时出错", ex);
            }
        }

        /// <summary>
        /// Parameter客户端专用消息处理
        /// </summary>
        private void ProcessParameterClientMessages(ReceivedMqttMessage receivedMessage)
        {
            try
            {
                _mqttTopicLogger.WriteProcessLog(receivedMessage.Topic, $"[Parameter客户端] 开始处理消息", "PARAMETER_PROCESS");

                // Parameter客户端专门处理参数下发消息
                if (receivedMessage.Topic.StartsWith("CPSET/SVDOWN/"))
                {
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[Parameter客户端] 检测到参数下发消息", "INFO");
                    _ = Task.Run(async () => await ProcessParameterDownloadMessage(receivedMessage));
                }
                else if (receivedMessage.Topic.StartsWith("CPSET/SVUP/"))
                {
                    // 处理参数回复确认（如果服务端会发送确认消息）
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[Parameter客户端] 接收到参数回复确认", "INFO");
                    ProcessParameterResponseConfirmation(receivedMessage);
                }
                else
                {
                     _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[Parameter客户端] 未知的参数相关主题");
                }
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[Parameter客户端] 处理消息时出错", ex);
            }
        }

        /// <summary>
        /// 处理参数回复确认消息
        /// </summary>
        private void ProcessParameterResponseConfirmation(ReceivedMqttMessage receivedMessage)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[Parameter客户端] 开始处理参数回复确认", "INFO");

                if (!IsValidJson(receivedMessage.Message))
                {
                     _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[Parameter客户端] 参数回复确认消息格式不是有效的JSON", new FormatException($"无效JSON: {receivedMessage.Message}"));
                    return;
                }

                var confirmationData = JsonConvert.DeserializeObject<dynamic>(receivedMessage.Message);
                
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, $"[Parameter客户端] 服务端确认消息: {receivedMessage.Message}", "INFO");
                
                // TODO: 实现参数回复确认的业务逻辑
                // 比如：更新参数状态、记录确认日志等
                
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[Parameter客户端] 参数回复确认处理完成", "INFO");
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[Parameter客户端] 处理参数回复确认时出错", ex);
            }
        }

        /// <summary>
        /// 处理参数上传客户端消息
        /// </summary>
        /// <param name="receivedMessage"></param>
        private void ProcessParameterUploadClientMessages(ReceivedMqttMessage receivedMessage)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "[ParameterUpload客户端] 处理消息", "INFO");
                
                // 参数上传客户端主要用于主动上传参数到IOT，通常不接收消息
                // 如果接收到消息，可能是IOT的确认或状态回复
                if (receivedMessage.Topic.Contains("CPSET/SVUP/"))
                {
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, $"[ParameterUpload客户端] 接收到IOT参数上传确认: {receivedMessage.Message}", "INFO");
                    // 这里可以处理IOT的确认消息
                }
                else
                {
                     _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[ParameterUpload客户端] 接收到未预期的消息");
                }
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "[ParameterUpload客户端] 处理消息时出错", ex);
            }
        }

        /// <summary>
        /// 处理参数上传消息（主动上传参数到IOT）
        /// </summary>
        /// <param name="receivedMessage"></param>
        private void ProcessParameterUploadMessage(ReceivedMqttMessage receivedMessage)
        {
            try
            {
                _mqttTopicLogger.WriteSystemInfo("开始处理参数上传任务");
                
                // 这个方法主要用于定时任务触发的参数上传
                // 从PLC读取参数组配置的所有参数值并上传到IOT
                UploadParametersToIOT();
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"处理参数上传消息时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 上传参数到IOT
        /// </summary>
        private async void UploadParametersToIOT()
        {
            try
            {
                _mqttTopicLogger.WriteSystemInfo("开始从PLC读取参数并上传到IOT");
                
                // 检查PLC连接
                if (_plcWrapper == null || !_plcWrapper.IsConnected)
                {
                    _mqttTopicLogger.WriteSystemError("PLC未连接，无法读取参数");
                    return;
                }

                // 从Parameter采集组中读取参数数据  
                // ParameterUpload和ParameterDownload共用Parameter采集组配置
                CollectionGroupConfig parameterGroup = null;
                if (!_collectionGroups.TryGetValue(AcquisitionType.Parameter, out parameterGroup))
                {
                    _mqttTopicLogger.WriteConfigOperation("检查配置", "Parameter采集组", "未找到Parameter采集组配置，请检查Config.xml");
                    return;
                }
                _mqttTopicLogger.WriteConfigOperation("参数读取", "Parameter采集组", "使用Parameter采集组配置读取参数");

                // 读取参数数据
                var readRequest = new PLCDataReadRequest
                {
                    StartAddress = parameterGroup.StartAddress,
                    Length = (ushort)parameterGroup.Length,
                    StorageName = "ParameterUpload",
                    DataType = PLCDataType.Float // 参数通常是Float类型
                };

                _mqttTopicLogger.WritePLCOperation("读取参数组", parameterGroup.StartAddress, $"长度: {parameterGroup.Length}", "开始");
                var result = await _plcWrapper._dataReader.ReadDataAsync(readRequest);
                
                if (!result.IsSuccess || result.Data == null)
                {
                    _mqttTopicLogger.WritePLCOperation("读取参数数据", parameterGroup.StartAddress, "", $"失败: {result.ErrorMessage}");
                    return;
                }

                // 解析参数数据
                var parameterData = await ParseParameterDataForUpload(result.Data, parameterGroup);
                
                if (parameterData.Count == 0)
                {
                    _mqttTopicLogger.WriteSystemError("未解析到任何参数数据");
                    return;
                }

                // 构建上传消息
                var uploadMessage = new ParameterUploadMessage
                {
                    taglist = new List<ParameterUploadTagList>
                    {
                        new ParameterUploadTagList
                        {
                            collection_items = parameterData,
                            device_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                        }
                    },
                    bu_id = BU_id,
                    district_id = District_id,
                    factory_id = Factory_id,
                    production_line_id = Production_line_id,
                    production_processes_id = production_processes_id,
                    work_center_id = Work_Center_id,
                    station_id = "",
                    device_name = Device_name
                };

                // 序列化并发送
                string jsonMessage = JsonConvert.SerializeObject(uploadMessage, Formatting.Indented);
                _mqttTopicLogger.WriteSystemInfo($"准备上传参数到IOT: {jsonMessage}");

                // 发送到参数上传主题
                await SendParameterUploadToIOT(jsonMessage);
                
                _mqttTopicLogger.WriteSystemInfo($"参数上传完成，共上传 {parameterData.Count} 个参数");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"上传参数到IOT时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 解析参数数据用于上传
        /// </summary>
        /// <param name="rawData"></param>
        /// <param name="parameterGroup"></param>
        /// <returns></returns>
        private async Task<Dictionary<string, object>> ParseParameterDataForUpload(byte[] rawData, CollectionGroupConfig parameterGroup)
        {
            var result = new Dictionary<string, object>();
            
            try
            {
                var plcDataParser = new PLCDataParser(_typeConfigs);
                var groupConfigs = parameterGroup.Types.Values.ToList();
                
                // 解析组数据
                var parsedData = plcDataParser.ParseGroupData(rawData, parameterGroup.StartAddress, parameterGroup.Length, groupConfigs);
                
                foreach (var kvp in parsedData)
                {
                    // 根据数据类型进行格式化
                    object formattedValue = FormatParameterValue(kvp.Value);
                    result[kvp.Key] = formattedValue;
                    
                    _mqttTopicLogger.WriteSystemInfo($"解析参数: {kvp.Key} = {formattedValue}");
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"解析参数数据时出错: {ex.Message}", ex);
            }
            
            return result;
        }

        /// <summary>
        /// 格式化参数值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private object FormatParameterValue(object value)
        {
            if (value == null) return "";
            
            // 根据类型进行格式化
            switch (value)
            {
                case float f:
                    return Math.Round(f, 1); // 保留1位小数
                case double d:
                    return Math.Round(d, 1);
                case int i:
                    return i.ToString();
                case short s:
                    return s.ToString();
                case bool b:
                    return b ? "1" : "0";
                default:
                    return value.ToString();
            }
        }

        /// <summary>
        /// 发送参数上传消息到IOT
        /// </summary>
        /// <param name="jsonMessage"></param>
        /// <returns></returns>
        private async Task SendParameterUploadToIOT(string jsonMessage)
        {
            try
            {
                // 获取参数上传客户端
                var uploadClient = GetMqttClientForAcquisitionType(AcquisitionType.ParameterUpload);
                if (uploadClient == null)
                {
                    _mqttTopicLogger.WriteSystemError("未找到参数上传MQTT客户端");
                    return;
                }

                // 参数上传使用 EVE/60J/EQP/{Device_name} 主题
                string uploadTopic = $"EVE/{Factory_id}/EQP/{Device_name}";
                if (_acquisitionTypeConfigs.TryGetValue(AcquisitionType.ParameterUpload, out var config) && !string.IsNullOrEmpty(config.MqttTopic))
                {
                    uploadTopic = config.MqttTopic;
                }

                // 发送消息
                var messageQueue = GetMqttMessageQueueForClient(uploadClient);
                messageQueue.Enqueue("ParameterUpload", uploadTopic, "ParameterUpload", jsonMessage);
                
                _mqttTopicLogger.WriteTopicLog(uploadTopic, "参数上传消息已加入队列", "INFO");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"发送参数上传消息时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取指定客户端的消息队列
        /// </summary>
        private MqttMessageQueue GetMqttMessageQueueForClient(MqttClientWrapper client)
        {
            try
            {
                if (clientMessageQueues.TryGetValue(client, out var messageQueue))
                {
                    return messageQueue;
                }

                // 如果是默认客户端，返回默认消息队列
                if (client == mqttClient)
                {
                    return _mqttMessageQueue;
                }

                _mqttTopicLogger.WriteWarning("消息队列", "未找到指定客户端的消息队列，使用默认消息队列");
                return _mqttMessageQueue;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"获取客户端消息队列时出错: {ex.Message}", ex);
                return _mqttMessageQueue;
            }
        }

        /// <summary>
        /// 订阅主题（向后兼容方法）
        /// </summary>
        /// <param name="topicToSubscribe"></param>
        private void SubscribeTopic(string topicToSubscribe)
        {
            mqttClient.OnMessageReceived += (timestamp, topic, message) =>
            {
                try
                {
                    // 处理接收到的MQTT消息
                    HandleReceivedMessage(timestamp, topic, message);
                }
                catch (Exception ex)
                {
                    _mqttTopicLogger.WriteSystemError($"处理接收到的MQTT消息时出错: {ex.Message}", ex);
                }
            };
            mqttClient.SubscribeMessage(topicToSubscribe, MqttClientWrapper.MessageFormat.Json, true);
        }

        /// <summary>
        /// 处理接收到的MQTT消息
        /// </summary>
        /// <param name="timestamp">时间戳</param>
        /// <param name="topic">主题</param>
        /// <param name="message">消息内容</param>
        private void HandleReceivedMessage(string timestamp, string topic, string message)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(topic, $"接收到MQTT消息 - 时间: {timestamp:yyyy-MM-dd HH:mm:ss.fff}", "INFO");
                _mqttTopicLogger.WriteTopicLog(topic, $"消息内容: {message}", "INFO");

                // 创建接收到的消息对象
                var receivedMessage = new ReceivedMqttMessage
                {
                    Timestamp = Convert.ToDateTime(timestamp),
                    Topic = topic,
                    Message = message,
                    Source = "External",
                    MessageType = DetermineMessageType(topic)
                };

                // 存储消息
                lock (_receivedMessagesLock)
                {
                    _receivedMessages.Add(receivedMessage);
                    
                    // 保持消息列表大小合理（最多保留1000条）
                    if (_receivedMessages.Count > 1000)
                    {
                        _receivedMessages.RemoveAt(0);
                    }
                }

                // 处理消息内容
                ProcessReceivedMessage(receivedMessage);
                
                // 触发消息接收事件
                OnMqttMessageReceived?.Invoke(receivedMessage);
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(topic, $"处理MQTT消息时出错: {ex.Message} | 消息内容: {message}", ex);
            }
        }

        /// <summary>
        /// 确定消息类型
        /// </summary>
        /// <param name="topic">主题</param>
        /// <returns>采集类型</returns>
        private AcquisitionType? DetermineMessageType(string topic)
        {
            try
            {
                // 根据主题匹配对应的采集类型
                foreach (var config in _acquisitionTypeConfigs)
                {
                    var typeConfig = config.Value;
                    
                    // 检查普通主题匹配
                    if (!string.IsNullOrEmpty(typeConfig.MqttTopic) && topic.Contains(typeConfig.MqttTopic))
                    {
                        _mqttTopicLogger.WriteTopicLog(topic, $"消息主题匹配采集类型: {config.Key}", "INFO");
                        return config.Key;
                    }
                    
                    // 检查机械臂主题匹配
                    if (typeConfig.IsRobot && !string.IsNullOrEmpty(typeConfig.RobotTopicPrefix))
                    {
                        if (topic.StartsWith(typeConfig.RobotTopicPrefix))
                        {
                            _mqttTopicLogger.WriteTopicLog(topic, $"机械臂消息主题匹配采集类型: {config.Key}", "INFO");
                            return config.Key;
                        }
                    }
                }

                // 检查参数相关主题
                if (topic.Contains("CPSET/SVDOWN/"))
                {
                    _mqttTopicLogger.WriteTopicLog(topic, "参数下发主题匹配采集类型: ParameterDownload", "INFO");
                    return AcquisitionType.ParameterDownload;
                }
                if (topic.Contains("CPSET/SVUP/"))
                {
                    _mqttTopicLogger.WriteTopicLog(topic, "参数回复确认主题 (此主题用于参数下发回复，不是参数上传)", "INFO");
                    return AcquisitionType.ParameterDownload; // 参数回复归属于参数下发流程
                }

                // 默认主题检查已迁移到动态配置中
                // Topic1已迁移到动态配置中，不再从此处判断
                if (topic.StartsWith(DEFAULT_ROBOT_TOPIC_PREFIX))
                {
                    return AcquisitionType.LoadingRobotic; // 默认机械臂类型
                }



                 _mqttTopicLogger.WriteErrorLog(topic, "无法确定主题的消息类型");
                return null;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"确定消息类型时出错: {ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 处理接收到的消息内容
        /// </summary>
        /// <param name="receivedMessage">接收到的消息</param>
        private void ProcessReceivedMessage(ReceivedMqttMessage receivedMessage)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, $"开始处理消息类型: {receivedMessage.MessageType?.ToString() ?? "Unknown"}", "INFO");

                // 检查是否是参数下发消息（特殊处理，但通常应该通过客户端组处理）
                if (receivedMessage.MessageType == null && receivedMessage.Topic.StartsWith("CPSET/SVDOWN/"))
                {
                    _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "通过通用处理方法处理参数下发消息（建议使用Parameter客户端组）", "INFO");
                    _ = Task.Run(async () => await ProcessParameterDownloadMessage(receivedMessage));
                }
                else if (receivedMessage.MessageType.HasValue)
                {
                    // 从配置中获取处理类型和处理方法
                    if (_acquisitionTypeConfigs.TryGetValue(receivedMessage.MessageType.Value, out var config))
                    {
                        if (!config.IsEnabled)
                        {
                            _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, $"消息类型 {receivedMessage.MessageType} 已被禁用，跳过处理", "INFO");
                            return;
                        }

                        if (_messageHandlers.TryGetValue(config.ProcessType, out var handler))
                        {
                            _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, $"使用配置化处理器: {config.ProcessType} 处理消息类型: {receivedMessage.MessageType}", "INFO");
                            handler(receivedMessage);
                        }
                        else
                        {
                             _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, $"未找到处理类型 '{config.ProcessType}' 对应的处理器，支持的处理类型: {string.Join(", ", _messageHandlers.Keys)}");
                            ProcessUnknownMessage(receivedMessage);
                        }
                    }
                    else
                    {
                         _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, $"未在配置中找到消息类型: {receivedMessage.MessageType}");
                        ProcessUnknownMessage(receivedMessage);
                    }
                }
                else
                {
                     _mqttTopicLogger.WriteErrorLog(receivedMessage.Topic, "消息类型为空且不是参数下发消息");
                    ProcessUnknownMessage(receivedMessage);
                }

                // 标记消息已处理
                receivedMessage.IsProcessed = true;
                _mqttTopicLogger.WriteTopicLog(receivedMessage.Topic, "消息处理完成", "INFO");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"处理消息内容时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 处理PPM类型消息
        /// </summary>
        /// <param name="message">消息</param>
        private void ProcessPPMMessage(ReceivedMqttMessage message)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(message.Topic, $"处理PPM消息: {message.Message}", "INFO");
                
                // 尝试解析JSON消息
                if (IsValidJson(message.Message))
                {
                    var ppmData = JsonConvert.DeserializeObject<dynamic>(message.Message);
                    _mqttTopicLogger.WriteTopicLog(message.Topic, $"PPM消息解析成功: {ppmData}", "INFO");
                    
                    // 在这里添加您的PPM消息处理逻辑
                    // 例如：存储到数据库、触发业务逻辑等
                }
                else
                {
                     _mqttTopicLogger.WriteErrorLog(message.Topic, "PPM消息格式不是有效的JSON", new FormatException($"无效JSON: {message.Message}"));
                }
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(message.Topic, "处理PPM消息时出错", ex);
            }
        }

        /// <summary>
        /// 处理轴/气缸类型消息
        /// </summary>
        /// <param name="message">消息</param>
        private void ProcessAxisMessage(ReceivedMqttMessage message)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(message.Topic, $"处理轴/气缸消息: {message.Message}", "INFO");
                
                if (IsValidJson(message.Message))
                {
                    var axisData = JsonConvert.DeserializeObject<dynamic>(message.Message);
                    _mqttTopicLogger.WriteTopicLog(message.Topic, $"轴/气缸消息解析成功: {axisData}", "INFO");
                    
                    // 在这里添加您的轴/气缸消息处理逻辑
                }
                else
                {
                     _mqttTopicLogger.WriteErrorLog(message.Topic, "轴/气缸消息格式不是有效的JSON", new FormatException($"无效JSON: {message.Message}"));
                }
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(message.Topic, "处理轴/气缸消息时出错", ex);
            }
        }

        /// <summary>
        /// 处理机械臂类型消息
        /// </summary>
        /// <param name="message">消息</param>
        private void ProcessRobotMessage(ReceivedMqttMessage message)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(message.Topic, $"处理机械臂消息: {message.Message}", "INFO");
                
                if (IsValidJson(message.Message))
                {
                    var robotData = JsonConvert.DeserializeObject<dynamic>(message.Message);
                    _mqttTopicLogger.WriteTopicLog(message.Topic, $"机械臂消息解析成功: {robotData}", "INFO");
                    
                    // 在这里添加您的机械臂消息处理逻辑
                    // 例如：控制指令、状态更新等
                }
                else
                {
                     _mqttTopicLogger.WriteErrorLog(message.Topic, "机械臂消息格式不是有效的JSON", new FormatException($"无效JSON: {message.Message}"));
                }
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(message.Topic, "处理机械臂消息时出错", ex);
            }
        }

        /// <summary>
        /// 处理未知类型消息
        /// </summary>
        /// <param name="message">消息</param>
        private void ProcessUnknownMessage(ReceivedMqttMessage message)
        {
            try
            {
                 _mqttTopicLogger.WriteErrorLog(message.Topic, $"处理未知类型消息 - 内容: {message.Message}");
                
                // 对于未知消息，可以选择记录或者进行通用处理
                if (IsValidJson(message.Message))
                {
                    var unknownData = JsonConvert.DeserializeObject<dynamic>(message.Message);
                    _mqttTopicLogger.WriteTopicLog(message.Topic, $"未知消息JSON解析成功: {unknownData}", "INFO");
                }
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(message.Topic, "处理未知消息时出错", ex);
            }
        }

        /// <summary>
        /// 检查字符串是否为有效的JSON
        /// </summary>
        /// <param name="jsonString">JSON字符串</param>
        /// <returns>是否有效</returns>
        private bool IsValidJson(string jsonString)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(jsonString))
                    return false;

                JsonConvert.DeserializeObject(jsonString);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 获取最近接收到的消息列表
        /// </summary>
        /// <param name="count">获取消息数量</param>
        /// <returns>消息列表</returns>
        public List<ReceivedMqttMessage> GetRecentMessages(int count = 50)
        {
            lock (_receivedMessagesLock)
            {
                return _receivedMessages
                    .OrderByDescending(m => m.Timestamp)
                    .Take(count)
                    .ToList();
            }
        }

        /// <summary>
        /// 获取指定类型的消息
        /// </summary>
        /// <param name="messageType">消息类型</param>
        /// <param name="count">获取消息数量</param>
        /// <returns>消息列表</returns>
        public List<ReceivedMqttMessage> GetMessagesByType(AcquisitionType messageType, int count = 20)
        {
            lock (_receivedMessagesLock)
            {
                return _receivedMessages
                    .Where(m => m.MessageType == messageType)
                    .OrderByDescending(m => m.Timestamp)
                    .Take(count)
                    .ToList();
            }
        }

        /// <summary>
        /// 获取指定客户端组的消息
        /// </summary>
        /// <param name="clientGroupName">客户端组名称</param>
        /// <param name="count">获取消息数量</param>
        /// <returns>消息列表</returns>
        public List<ReceivedMqttMessage> GetMessagesByClientGroup(string clientGroupName, int count = 20)
        {
            lock (_clientGroupMessagesLock)
            {
                if (clientGroupMessages.TryGetValue(clientGroupName, out var messages))
                {
                    return messages
                        .OrderByDescending(m => m.Timestamp)
                        .Take(count)
                        .ToList();
                }
                return new List<ReceivedMqttMessage>();
            }
        }

        /// <summary>
        /// 获取所有客户端组的消息统计
        /// </summary>
        /// <returns>客户端组消息统计</returns>
        public Dictionary<string, int> GetClientGroupMessageStats()
        {
            lock (_clientGroupMessagesLock)
            {
                return clientGroupMessages.ToDictionary(
                    kvp => kvp.Key,
                    kvp => kvp.Value.Count
                );
            }
        }

        /// <summary>
        /// 获取客户端组列表和状态
        /// </summary>
        /// <returns>客户端组状态信息</returns>
        public Dictionary<string, object> GetClientGroupStatus()
        {
            var status = new Dictionary<string, object>();

            foreach (var clientGroup in _mqttClientGroups)
            {
                var groupInfo = new Dictionary<string, object>
                {
                    ["Name"] = clientGroup.Value.Name,
                    ["ClientId"] = clientGroup.Value.ClientId,
                    ["Description"] = clientGroup.Value.Description,
                    ["IsEnabled"] = clientGroup.Value.IsEnabled,
                    ["AcquisitionTypes"] = clientGroup.Value.AcquisitionTypes,
                    ["CollectionIntervalMs"] = clientGroup.Value.CollectionIntervalMs,
                    ["IsConnected"] = mqttClients.TryGetValue(clientGroup.Key, out var client) ? client.IsConnected : false,
                    ["MessageCount"] = GetMessagesByClientGroup(clientGroup.Key, int.MaxValue).Count
                };

                status[clientGroup.Key] = groupInfo;
            }

            return status;
        }

        /// <summary>
        /// 获取MQTT主题日志统计信息
        /// </summary>
        /// <param name="date">日期，默认为今天</param>
        /// <returns>主题日志统计信息</returns>
        public Dictionary<string, object> GetMqttTopicLogStatistics(DateTime? date = null)
        {
            try
            {
                var statistics = _mqttTopicLogger.GetTopicLogStatistics(date);
                return new Dictionary<string, object>
                {
                    ["Date"] = (date ?? DateTime.Now).ToString("yyyy-MM-dd"),
                    ["TopicCount"] = statistics.Count,
                    ["TopicStats"] = statistics.Select(kvp => new 
                    {
                        Topic = kvp.Key,
                        LogSizeBytes = kvp.Value,
                        LogSizeKB = Math.Round(kvp.Value / 1024.0, 2)
                    }).ToList()
                };
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"获取MQTT主题日志统计信息时出错: {ex.Message}", ex);
                return new Dictionary<string, object> { ["Error"] = ex.Message };
            }
        }

        /// <summary>
        /// 获取分类日志统计信息
        /// </summary>
        /// <param name="date">日期，默认为今天</param>
        /// <returns>分类日志统计信息</returns>
        public Dictionary<string, object> GetCategoryLogStatistics(DateTime? date = null)
        {
            try
            {
                var statistics = _mqttTopicLogger.GetCategoryLogStatistics(date);
                return new Dictionary<string, object>
                {
                    ["Date"] = (date ?? DateTime.Now).ToString("yyyy-MM-dd"),
                    ["CategoryCount"] = statistics.Count,
                    ["CategoryStats"] = statistics.Select(kvp => new 
                    {
                        Category = kvp.Key,
                        LogSizeBytes = kvp.Value,
                        LogSizeKB = Math.Round(kvp.Value / 1024.0, 2)
                    }).ToList()
                };
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"获取分类日志统计信息时出错: {ex.Message}", ex);
                return new Dictionary<string, object> { ["Error"] = ex.Message };
            }
        }

        /// <summary>
        /// 清理过期的MQTT主题日志
        /// </summary>
        /// <param name="retentionDays">保留天数</param>
        /// <returns>清理结果</returns>
        public Dictionary<string, object> CleanupMqttTopicLogs(int retentionDays = 30)
        {
            try
            {
                _mqttTopicLogger.CleanupOldLogs(retentionDays);
                return new Dictionary<string, object>
                {
                    ["Success"] = true,
                    ["Message"] = $"已清理超过 {retentionDays} 天的MQTT主题日志",
                    ["RetentionDays"] = retentionDays
                };
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"清理MQTT主题日志时出错: {ex.Message}", ex);
                return new Dictionary<string, object>
                {
                    ["Success"] = false,
                    ["Error"] = ex.Message
                };
            }
        }

        /// <summary>
        /// 获取指定主题的日志文件路径
        /// </summary>
        /// <param name="topic">MQTT主题</param>
        /// <param name="date">日期，默认为今天</param>
        /// <returns>日志文件路径信息</returns>
        public Dictionary<string, object> GetTopicLogFilePath(string topic, DateTime? date = null)
        {
            try
            {
                string logFilePath = _mqttTopicLogger.GetTopicLogFilePath(topic, date);
                bool fileExists = File.Exists(logFilePath);
                long fileSize = fileExists ? new FileInfo(logFilePath).Length : 0;

                return new Dictionary<string, object>
                {
                    ["Topic"] = topic,
                    ["Date"] = (date ?? DateTime.Now).ToString("yyyy-MM-dd"),
                    ["LogFilePath"] = logFilePath,
                    ["FileExists"] = fileExists,
                    ["FileSizeBytes"] = fileSize,
                    ["FileSizeKB"] = Math.Round(fileSize / 1024.0, 2)
                };
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"获取主题日志文件路径时出错: {ex.Message}", ex);
                return new Dictionary<string, object>
                {
                    ["Topic"] = topic,
                    ["Error"] = ex.Message
                };
            }
        }

        /// <summary>
        /// 处理参数下发消息的包装器（用于消息处理器字典）
        /// </summary>
        /// <param name="message">接收到的参数下发消息</param>
        private void ProcessParameterDownloadMessageWrapper(ReceivedMqttMessage message)
        {
            _ = Task.Run(async () => await ProcessParameterDownloadMessage(message));
        }

        /// <summary>
        /// 处理参数下发消息
        /// </summary>
        /// <param name="message">接收到的参数下发消息</param>
        private async Task ProcessParameterDownloadMessage(ReceivedMqttMessage message)
        {
            try
            {
                _mqttTopicLogger.WriteTopicLog(message.Topic, $"开始处理参数下发消息: {message.Message}", "INFO");
                
                // 解析JSON消息
                if (!IsValidJson(message.Message))
                {
                     _mqttTopicLogger.WriteErrorLog(message.Topic, "参数下发消息格式不是有效的JSON", new FormatException($"无效JSON: {message.Message}"));
                    return;
                }

                var parameterMessage = JsonConvert.DeserializeObject<ParameterDownloadMessage>(message.Message);
                
                if (parameterMessage?.Head == null || parameterMessage.Body == null)
                {
                     _mqttTopicLogger.WriteErrorLog(message.Topic, "参数下发消息格式错误：缺少Head或Body部分");
                    return;
                }

                _mqttTopicLogger.WriteTopicLog(message.Topic, $"接收到参数下发命令 - 方法: {parameterMessage.Head.MethodName}, 设备: {parameterMessage.Head.EquipmentCode}, 消息ID: {parameterMessage.Head.MessageId}", "INFO");
                _mqttTopicLogger.WriteTopicLog(message.Topic, $"参数数量: {parameterMessage.Body.Count}", "INFO");

                // 处理命令
                switch (parameterMessage.Head.MethodName?.ToUpper())
                {
                    case "WRITECMD":
                        await ProcessWriteCommand(parameterMessage);
                        break;
                        
                    default:
                         _mqttTopicLogger.WriteErrorLog(message.Topic, $"不支持的参数下发方法: {parameterMessage.Head.MethodName}");
                        SendParameterResponse(parameterMessage, false, "不支持的命令方法");
                        break;
                }
            }
            catch (Exception ex)
            {
                 _mqttTopicLogger.WriteErrorLog(message.Topic, "处理参数下发消息时出错", ex);
            }
        }

        /// <summary>
        /// 处理写入命令
        /// </summary>
        /// <param name="parameterMessage">参数消息</param>
        private async Task ProcessWriteCommand(ParameterDownloadMessage parameterMessage)
        {
            try
            {
                _mqttTopicLogger.WriteProcessLog("CPSET/SVDOWN", $"开始执行写入命令，参数数量: {parameterMessage.Body.Count}", "WRITE_CMD_START");
                
                var responseBody = new List<ParameterResponseBody>();
                bool allSuccess = true;

                foreach (var parameter in parameterMessage.Body)
                {
                    _mqttTopicLogger.WriteParameterLog("CPSET/SVDOWN", "开始写入", parameter.ItemCode, parameter.ItemValue, "准备写入");
                    
                    try
                    {
                        // 执行PLC参数写入
                        bool writeResult = await WritePLCParameter(parameter.ItemCode, parameter.ItemValue);
                        
                        var responseItem = new ParameterResponseBody
                        {
                            ItemCode = parameter.ItemCode,
                            ItemValue = parameter.ItemValue,
                            WriteResult = writeResult ? "1" : "0"
                        };
                        
                        responseBody.Add(responseItem);
                        
                        if (!writeResult)
                        {
                            allSuccess = false;
                            _mqttTopicLogger.WritePLCOperation("写入参数", parameter.ItemCode, parameter.ItemValue, "失败");
                        }
                        else
                        {
                            _mqttTopicLogger.WriteParameterLog("CPSET/SVDOWN", "写入成功", parameter.ItemCode, parameter.ItemValue, "成功");
                        }
                    }
                    catch (Exception ex)
                    {
                        _mqttTopicLogger.WriteSystemError($"写入参数 {parameter.ItemCode} 时出错: {ex.Message}", ex);
                        
                        var responseItem = new ParameterResponseBody
                        {
                            ItemCode = parameter.ItemCode,
                            ItemValue = parameter.ItemValue,
                            WriteResult = "0"
                        };
                        
                        responseBody.Add(responseItem);
                        allSuccess = false;
                    }
                }

                // 发送回复消息
                SendParameterResponse(parameterMessage, allSuccess, "", responseBody);
                
                _mqttTopicLogger.WriteSystemInfo($"写入命令执行完成，总体结果: {(allSuccess ? "成功" : "部分失败")}");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"处理写入命令时出错: {ex.Message}", ex);
                SendParameterResponse(parameterMessage, false, $"命令执行异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 写入PLC参数
        /// </summary>
        /// <param name="itemCode">参数代码</param>
        /// <param name="itemValue">参数值</param>
        /// <returns>写入是否成功</returns>
        private async Task<bool> WritePLCParameter(string itemCode, string itemValue)
        {
            try
            {
                // 检查PLC连接状态
                if (_plcWrapper == null || !_plcWrapper.IsConnected)
                {
                    _mqttTopicLogger.WriteSystemError("PLC未连接，无法写入参数");
                    return false;
                }

                _mqttTopicLogger.WritePLCOperation("写入参数", itemCode, itemValue, "开始");

                // TODO: 这里需要根据您的实际PLC写入接口来实现
                // 示例实现（需要根据实际PLC通信库调整）：
                
                // 解析参数代码，确定PLC地址
                string plcAddress = MapItemCodeToPLCAddress(itemCode);
                if (string.IsNullOrEmpty(plcAddress))
                {
                    _mqttTopicLogger.WriteSystemError($"无法映射参数代码到PLC地址: {itemCode}");
                    return false;
                }

                // 根据参数类型确定数据类型和写入方法
                bool writeSuccess = await WriteToPLCAddress(plcAddress, itemValue);
                
                if (writeSuccess)
                {
                    _mqttTopicLogger.WritePLCOperation("写入参数", plcAddress, itemValue, "成功");
                }
                else
                {
                    _mqttTopicLogger.WritePLCOperation("写入参数", plcAddress, itemValue, "失败");
                }

                return writeSuccess;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"写入PLC参数时出错: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 映射参数代码到PLC地址
        /// </summary>
        /// <param name="itemCode">参数代码</param>
        /// <returns>PLC地址</returns>
        private string MapItemCodeToPLCAddress(string itemCode)
        {
            try
            {
                // 从Config.xml中的Parameter组获取参数地址映射
                if (_collectionGroups.TryGetValue(AcquisitionType.Parameter, out var parameterGroup))
                {
                    // 在Parameter组的Types字典中查找对应的参数地址
                    var foundItem = parameterGroup.Types.Values.FirstOrDefault(typeConfig => 
                        string.Equals(typeConfig.Name, itemCode, StringComparison.OrdinalIgnoreCase));
                    
                    if (foundItem != null)
                    {
                        _mqttTopicLogger.WriteProcessLog("PARAMETER_MAPPING", $"参数映射成功: {itemCode} → {foundItem.Address}", "MAPPING_SUCCESS");
                        return foundItem.Address;
                    }
                }
                
                _mqttTopicLogger.WriteConfigOperation("参数映射", "Parameter组", $"未找到参数代码映射: {itemCode}");
                _mqttTopicLogger.WriteConfigOperation("参数映射", "Parameter组", "可用的参数代码列表:");
                
                // 打印可用的参数代码以便调试
                if (_collectionGroups.TryGetValue(AcquisitionType.Parameter, out var paramGroup))
                {
                    foreach (var typeConfig in paramGroup.Types.Values)
                    {
                        _mqttTopicLogger.WriteConfigOperation("参数映射", "Parameter组", $"  - {typeConfig.Name} → {typeConfig.Address}");
                    }
                }
                
                return null;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"映射参数代码到PLC地址时出错: {ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 写入PLC地址
        /// </summary>
        /// <param name="address">PLC地址</param>
        /// <param name="value">要写入的值</param>
        /// <returns>写入是否成功</returns>
        private async Task<bool> WriteToPLCAddress(string address, string value)
        {
            try
            {
                if (_plcWrapper == null || !_plcWrapper.IsConnected)
                {
                    _mqttTopicLogger.WriteSystemError("PLC未连接，无法写入数据");
                    return false;
                }
                
                // 从Parameter组配置中获取数据类型
                string dataType = GetParameterDataType(address);
                _mqttTopicLogger.WriteProcessLog("PLC_WRITE", $"写入PLC地址: {address} = {value}, 数据类型: {dataType}", "PLC_WRITE_START");
                
                // 根据数据类型进行写入
                switch (dataType?.ToUpper())
                {
                    case "FLOAT":
                        if (float.TryParse(value, out float floatValue))
                        {
                            return await _plcWrapper._dataReader.WriteFloatAsync(address, floatValue);
                        }
                        else
                        {
                            _mqttTopicLogger.WriteSystemError($"无法将值转换为Float类型: {value}");
                            return false;
                        }
                        
                    case "SHORT":
                    case "INT":
                        if (short.TryParse(value, out short shortValue))
                        {
                            return await _plcWrapper._dataReader.WriteShortAsync(address, shortValue);
                        }
                        else
                        {
                            _mqttTopicLogger.WriteSystemError($"无法将值转换为Short类型: {value}");
                            return false;
                        }
                        
                    case "BOOL":
                        if (bool.TryParse(value, out bool boolValue))
                        {
                            return await _plcWrapper._dataReader.WriteBoolAsync(address, boolValue);
                        }
                        else
                        {
                            _mqttTopicLogger.WriteSystemError($"无法将值转换为Bool类型: {value}");
                            return false;
                        }
                        
                    default:
                        // 默认按字符串处理
                        _mqttTopicLogger.WriteProcessLog("PLC_WRITE", $"使用默认字符串方式写入PLC地址: {address}", "DEFAULT_STRING_WRITE");
                        return await _plcWrapper._dataReader.WriteStringAsync(address, value);
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"写入PLC地址时出错: {ex.Message}");
                return false;
            }
        }
        
        /// <summary>
        /// 获取参数的数据类型
        /// </summary>
        /// <param name="address">PLC地址</param>
        /// <returns>数据类型</returns>
        private string GetParameterDataType(string address)
        {
            try
            {
                if (_collectionGroups.TryGetValue(AcquisitionType.Parameter, out var parameterGroup))
                {
                    var foundItem = parameterGroup.Types.Values.FirstOrDefault(typeConfig => 
                        string.Equals(typeConfig.Address, address, StringComparison.OrdinalIgnoreCase));
                    
                    if (foundItem != null)
                    {
                        return foundItem.DataType;
                    }
                }
                
                _mqttTopicLogger.WriteErrorLog("PLC_WRITE", $"未找到地址 {address} 的数据类型配置，使用默认类型 Float");
                return "Float"; // 默认为Float类型，因为Config.xml中Parameter组大部分都是Float
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"获取参数数据类型时出错: {ex.Message}");
                return "Float";
            }
        }

        /// <summary>
        /// 发送参数回复消息
        /// </summary>
        /// <param name="originalMessage">原始下发消息</param>
        /// <param name="success">整体是否成功</param>
        /// <param name="errorMessage">错误消息</param>
        /// <param name="responseBody">回复消息体</param>
        private void SendParameterResponse(ParameterDownloadMessage originalMessage, bool success, string errorMessage = "", List<ParameterResponseBody> responseBody = null)
        {
            try
            {
                // 构建回复消息
                var responseMessage = new ParameterResponseMessage
                {
                    Head = new ParameterHead
                    {
                        MethodName = originalMessage.Head.MethodName,
                        BuStation = originalMessage.Head.BuStation,
                        FactoryCode = originalMessage.Head.FactoryCode,
                        ProductionLineCode = originalMessage.Head.ProductionLineCode,
                        ProcessCode = originalMessage.Head.ProcessCode,
                        EquipmentCode = originalMessage.Head.EquipmentCode,
                        MessageId = originalMessage.Head.MessageId // 保持相同的MessageId
                    },
                    Body = responseBody ?? new List<ParameterResponseBody>()
                };

                // 如果整体失败且没有具体的responseBody，创建通用错误回复
                if (!success && (responseBody == null || responseBody.Count == 0))
                {
                    foreach (var param in originalMessage.Body)
                    {
                        responseMessage.Body.Add(new ParameterResponseBody
                        {
                            ItemCode = param.ItemCode,
                            ItemValue = param.ItemValue,
                            WriteResult = "0"
                        });
                    }
                }

                // 序列化回复消息
                string responseJson = JsonConvert.SerializeObject(responseMessage, new JsonSerializerSettings 
                { 
                    NullValueHandling = NullValueHandling.Ignore, 
                    Formatting = Formatting.None 
                });

                // 发送回复到上行主题
                string responseTopic = $"CPSET/SVUP/{Device_name}";
                
                _mqttTopicLogger.WriteMessageSent(responseTopic, responseJson, "ParameterResponse");
                _mqttTopicLogger.WriteProcessLog(responseTopic, "参数回复消息准备发送", "PARAMETER_RESPONSE");

                // 使用参数下发专用客户端发送回复
                var parameterClient = GetMqttClientForMessageType("ParameterDownload");
                var parameterQueue = GetMqttMessageQueueForClient(parameterClient);
                parameterQueue.Enqueue("ParameterResponse", responseTopic, "ParameterResponse", responseJson);
                
                _mqttTopicLogger.WriteProcessLog(responseTopic, $"参数回复消息已发送 - MessageId: {originalMessage.Head.MessageId}, 结果: {(success ? "成功" : "失败")}", "RESPONSE_SENT");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"发送参数回复消息时出错: {ex.Message}");
            }
        }





        /// <summary>
        /// 字符串发布消息
        /// </summary>
        /// <param name="source"></param>
        /// <param name="publishTopic"></param>
        /// <param name="type"></param>
        /// <param name="messageObj"></param>
        /// <returns></returns>
        private async Task SendMqttAsync(string source, string publishTopic, string type, string messageObj)
        {
            try
            {
                if (publishTopic != null)
                {
                    MqttClientWrapper targetClient = null;
                    
                    // 根据消息类型选择合适的客户端
                    if (Enum.TryParse<AcquisitionType>(type, out var acquisitionType))
                    {
                        targetClient = GetMqttClientForAcquisitionType(acquisitionType);
                        
                        // 特殊处理机械臂数据的主题
                        if (_acquisitionTypeConfigs.TryGetValue(acquisitionType, out var config) && config.IsRobot)
                    {
                        var groupConfig = _collectionGroups[acquisitionType];
                        string robotTopicPrefix = !string.IsNullOrEmpty(config.RobotTopicPrefix) 
                            ? config.RobotTopicPrefix 
                            : DEFAULT_ROBOT_TOPIC_PREFIX;
                        publishTopic = $"{robotTopicPrefix}{groupConfig.RobotName}";
                        _mqttTopicLogger.WriteProcessLog(publishTopic, $"机械臂主题调整为: {publishTopic}", "TOPIC_ADJUST");
                        }
                    }
                    
                    // 如果没有找到特定客户端或客户端未连接，使用默认客户端
                    if (targetClient == null || !targetClient.IsConnected)
                    {
                        if (mqttClient != null && mqttClient.IsConnected)
                        {
                            targetClient = mqttClient;
                            _mqttTopicLogger.WriteSystemInfo($"使用默认MQTT客户端发送消息到主题: {publishTopic}");
                            _mqttTopicLogger.WriteProcessLog(publishTopic, "使用默认MQTT客户端发送消息", "CLIENT_FALLBACK");
                        }
                        else
                        {
                            _mqttTopicLogger.WriteSystemError($"无可用的MQTT客户端发送消息到主题: {publishTopic}");
                            _mqttTopicLogger.WriteErrorLog(publishTopic, "无可用的MQTT客户端发送消息");
                            return;
                        }
                    }

                    // 记录消息发送日志
                    _mqttTopicLogger.WriteMessageSent(publishTopic, messageObj, source);
                    
                    await targetClient.SendMessageAsync(source, publishTopic, type, messageObj);
                    _mqttTopicLogger.WriteSystemInfo($"消息已发送到主题: {publishTopic} (客户端: {targetClient.GetHashCode()})");
                    
                    // 记录发送成功日志
                    _mqttTopicLogger.WriteProcessLog(publishTopic, $"消息发送成功 (客户端: {targetClient.GetHashCode()})", "SEND_SUCCESS");
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"发布信息失败: {ex.Message}");
                _mqttTopicLogger.WriteErrorLog(publishTopic, $"发布信息失败: {ex.Message}", ex);
            }
        }
        #endregion


        #region 创建定时线程
        /// <summary>
        /// 有变化数据采集线程
        /// </summary>
        /// <param name="workerId"></param>
        /// <param name="ct"></param>
        /// <returns></returns>

        private async Task RunChangeDetectionTaskAsync(CancellationToken ct)
        {
            _mqttTopicLogger.WriteSystemInfo("数据采集循环任务开始运行");
            
            while (!ct.IsCancellationRequested)
                {
                    try
                    {
                    // 检查PLC连接状态
                    if (_plcWrapper == null)
                    {
                        _mqttTopicLogger.WriteSystemError("PLC包装器为空，等待重新初始化...");
                        await Task.Delay(5000, ct);
                        continue;
                    }

                    if (!_plcWrapper.IsConnected)
                    {
                        _mqttTopicLogger.WriteSystemInfo("PLC未连接，尝试快速重连...");
                        
                        // 尝试快速重连
                        bool quickReconnected = await AttemptQuickReconnection(ct);
                        if (!quickReconnected)
                        {
                            _mqttTopicLogger.WriteSystemInfo("快速重连失败，等待后台监控任务处理，继续采集循环...");
                        await Task.Delay(2000, ct);
                        continue;
                        }
                        else
                        {
                            _mqttTopicLogger.WriteSystemInfo("快速重连成功，继续数据采集");
                        }
                    }

                    // 执行数据采集
                        await CollectAndPublishData("ChangeTask", AcqTypes);
                    await Task.Delay(ThreadInterval, ct);
                    }
                    catch (OperationCanceledException)
                    {
                    _mqttTopicLogger.WriteSystemInfo("数据采集任务被正常取消");
                    break;
                    }
                    catch (Exception ex)
                    {
                    _mqttTopicLogger.WriteSystemError($"数据采集循环错误: {ex.Message}");
                    // 发生错误时等待更长时间再重试
                    await Task.Delay(5000, ct);
                    }
                }
            
            _mqttTopicLogger.WriteSystemInfo("数据采集循环任务已停止");
        }
        #endregion


        private async Task CollectAndPublishData(string source, AcquisitionType[] types)
        {
            const int maxRetries = 3;
            var plcDataParser = new PLCDataParser(_typeConfigs);
            var sw = new Stopwatch();

            // 前置检查
            if (types == null || !types.Any())
            {
                _mqttTopicLogger.WriteSystemError("采集类型数组为空，跳过数据采集");
                return;
            }

            // 检查PLC连接状态
            if (_plcWrapper == null)
            {
                _mqttTopicLogger.WriteSystemError("PLC包装器未初始化");
                return;
            }

            if (!_plcWrapper.IsConnected)
            {
                _mqttTopicLogger.WriteSystemInfo("PLC未连接，尝试快速重连...");
                if (!await AttemptQuickReconnection(_cts.Token))
                {
                    _mqttTopicLogger.WriteSystemInfo("PLC快速重连失败，跳过本次数据采集（后台任务将继续尝试重连）");
                    return;
                }
                else
                {
                    _mqttTopicLogger.WriteSystemInfo("PLC快速重连成功，继续数据采集");
                }
            }

            _mqttTopicLogger.WriteSystemInfo($"开始数据采集，目标类型: [{string.Join(", ", types)}]，PLC状态: {(_plcWrapper.IsConnected ? "已连接" : "未连接")}");

            for (int retry = 0; retry < maxRetries; retry++)
            {
                try
                {
                    sw.Restart();
                    _mqttTopicLogger.WriteSystemInfo($"开始第 {retry + 1} 次数据采集尝试，PLC地址: {PlcIpAddress}:{PlcPort}");

                    // 准备读取请求
                    var requests = new List<PLCDataReadRequest>();
                    foreach (var type in types)
                    {
                        if (!_collectionGroups.TryGetValue(type, out var config))
                        {
                            _mqttTopicLogger.WriteSystemError($"未找到类型 {type} 的配置信息，已配置类型: [{string.Join(", ", _collectionGroups.Keys)}]");
                            continue;
                        }

                        // 检查配置是否启用
                        if (_acquisitionTypeConfigs.TryGetValue(type, out var typeConfig) && !typeConfig.IsEnabled)
                        {
                            _mqttTopicLogger.WriteSystemInfo($"类型 {type} 已禁用，跳过采集");
                            continue;
                        }

                        var request = new PLCDataReadRequest
                        {
                            StartAddress = config.StartAddress,
                            Length = (ushort)config.Length,
                            StorageName = config.Name,
                            DataType = PLCDataType.Float // 采集组默认使用Float类型
                        };

                        requests.Add(request);
                        _mqttTopicLogger.WriteSystemInfo($"添加读取请求: {type} -> {config.StartAddress}, 长度: {config.Length}");
                    }

                    if (!requests.Any())
                    {
                        _mqttTopicLogger.WriteSystemError("没有有效的数据请求，可能所有类型都被禁用或配置缺失");
                        return;
                    }

                    _mqttTopicLogger.WriteSystemInfo($"准备执行 {requests.Count} 个并发读取任务");

                    // 创建并发任务列表，添加更详细的错误处理
                    var readTasks = requests.Select(async request =>
                    {
                        try
                        {
                            _mqttTopicLogger.WriteSystemInfo($"开始读取 {request.StorageName}: {request.StartAddress}, 长度: {request.Length}");
                            
                            // 检查PLC连接状态
                            if (!_plcWrapper.IsConnected)
                            {
                                throw new Exception($"PLC连接已断开，无法读取 {request.StorageName}");
                            }

                            var result = await _plcWrapper._dataReader.ReadDataAsync(request);
                            
                            if (!result.IsSuccess)
                            {
                                _mqttTopicLogger.WriteSystemError($"读取 {request.StorageName} 失败: {result.ErrorMessage}");
                                throw new Exception($"PLC读取错误 [{request.StorageName}]: {result.ErrorMessage}");
                            }

                            if (result.Data == null || result.Data.Length == 0)
                            {
                                _mqttTopicLogger.WriteSystemError($"读取 {request.StorageName} 返回空数据");
                                throw new Exception($"PLC返回空数据 [{request.StorageName}]");
                            }

                            _mqttTopicLogger.WriteSystemInfo($"成功读取 {request.StorageName}: {result.Data.Length} 字节");
                            return (request.StorageName, result.Data);
                        }
                        catch (Exception ex)
                        {
                            _mqttTopicLogger.WriteSystemError($"处理请求 {request.StorageName} 时出错: {ex.Message}\n堆栈: {ex.StackTrace}");
                            throw new Exception($"读取任务失败 [{request.StorageName}]: {ex.Message}", ex);
                        }
                    }).ToList();

                    // 等待所有任务完成
                    var results = await Task.WhenAll(readTasks);
                    _mqttTopicLogger.WriteSystemInfo($"所有读取任务完成，成功获取 {results.Length} 个数据块");

                    // 并发处理数据，添加更好的错误隔离
                    var processingTasks = results.Select(async result =>
                    {
                        try
                        {
                            _mqttTopicLogger.WriteSystemInfo($"开始处理数据: {result.StorageName}");
                            await ProcessPLCData(source, result.StorageName, result.Data);
                            _mqttTopicLogger.WriteSystemInfo($"数据处理完成: {result.StorageName}");
                        }
                        catch (Exception ex)
                        {
                            // 数据处理错误不应该导致整个采集失败
                            _mqttTopicLogger.WriteSystemError($"处理数据 {result.StorageName} 时出错: {ex.Message}\n堆栈: {ex.StackTrace}");
                            // 不再抛出异常，允许其他数据继续处理
                        }
                    });

                    // 等待所有处理任务完成
                    await Task.WhenAll(processingTasks);

                    sw.Stop();
                    _mqttTopicLogger.WriteSystemInfo($"数据采集完成，耗时: {sw.ElapsedMilliseconds}ms，处理了 {results.Length} 个数据块");
                    break; // 成功后跳出重试循环
                }
                catch (Exception ex)
                {
                    sw.Stop();
                    _mqttTopicLogger.WriteSystemError($"数据采集出错(尝试 {retry + 1}/{maxRetries}): {ex.Message}\n异常类型: {ex.GetType().Name}\n堆栈跟踪: {ex.StackTrace}");

                    // 检查是否是连接相关的错误
                    bool isConnectionError = ex.Message.Contains("连接") || ex.Message.Contains("网络") || 
                                           ex.Message.Contains("超时") || ex.Message.Contains("PLC");

                    if (retry == maxRetries - 1)
                    {
                        _mqttTopicLogger.WriteSystemError($"达到最大重试次数({maxRetries})，放弃采集。最后错误: {ex.Message}");
                        
                        // 如果是连接错误，不抛出异常，允许下次循环继续尝试
                        if (isConnectionError)
                        {
                            _mqttTopicLogger.WriteSystemError("检测到连接错误，将在下次循环中继续尝试");
                            return;
                        }
                        throw;
                    }

                    // 如果是连接错误，尝试快速重连
                    if (isConnectionError)
                    {
                        _mqttTopicLogger.WriteSystemInfo("检测到连接错误，尝试快速重连PLC...");
                        if (!await AttemptQuickReconnection(_cts.Token))
                    {
                            _mqttTopicLogger.WriteSystemError("PLC快速重连失败，将在下次尝试中继续（后台监控任务将持续重连）");
                            if (retry < maxRetries - 1)
                            {
                                await Task.Delay(2000); // 等待更长时间
                                continue;
                            }
                            // 即使快速重连失败，也不要完全退出，让循环继续
                            break; // 跳出重试循环，但不退出整个方法
                        }
                        else
                        {
                            _mqttTopicLogger.WriteSystemInfo("PLC快速重连成功，准备重试数据采集");
                        }
                    }

                    // 重连成功后等待一段时间再继续
                    await Task.Delay(1000);
                }
            }
        }

        /// <summary>
        /// 快速重连PLC（用于数据采集任务中的快速恢复）
        /// </summary>
        /// <param name="ct">取消令牌</param>
        /// <returns>是否重连成功</returns>
        private async Task<bool> AttemptQuickReconnection(CancellationToken ct)
        {
            try
            {
                if (_plcWrapper == null)
                {
                    return false;
                }

                _mqttTopicLogger.WriteSystemInfo("执行快速PLC重连...");
                
                // 尝试一次重连，不进行多次重试（避免阻塞数据采集循环）
                bool reconnected = await _plcWrapper.ReconnectAsync();
                
                if (reconnected && _plcWrapper.IsConnected)
                {
                    _mqttTopicLogger.WriteSystemInfo("快速PLC重连成功");
                    return true;
                }
                else
                {
                    _mqttTopicLogger.WriteSystemInfo("快速PLC重连失败");
                    return false;
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"快速PLC重连过程中出错: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 重连PLC（完整重连流程，用于后台监控任务）
        /// </summary>
        /// <param name="ct"></param>
        /// <returns></returns>
        private async Task<bool> AttemptReconnection(CancellationToken ct)
        {
            const int MaxReconnectAttempts = 3;
            const int ReconnectionInterval = 5000; // 5 seconds

            _mqttTopicLogger.WriteSystemInfo($"开始PLC重连流程，目标地址: {PlcIpAddress}:{PlcPort}");

            for (int attempt = 1; attempt <= MaxReconnectAttempts; attempt++)
            {
                if (ct.IsCancellationRequested)
                {
                    _mqttTopicLogger.WriteSystemError("重连过程被取消");
                    return false;
                }

                try
                {
                    _mqttTopicLogger.WriteSystemInfo($"尝试重新连接PLC，第 {attempt}/{MaxReconnectAttempts} 次尝试");
                    
                    // 先断开当前连接
                    if (_plcWrapper != null)
                    {
                        try
                        {
                            _plcWrapper.Disconnect();
                            _mqttTopicLogger.WriteSystemInfo("已断开现有PLC连接");
                        }
                        catch (Exception ex)
                        {
                            _mqttTopicLogger.WriteSystemError($"断开PLC连接时出错: {ex.Message}");
                        }
                    }

                    // 等待一段时间再重连
                    await Task.Delay(1000, ct);

                    // 尝试重新连接
                bool reconnected = await _plcWrapper.ReconnectAsync();
                    
                    if (reconnected && _plcWrapper.IsConnected)
                    {
                        _mqttTopicLogger.WriteSystemInfo($"PLC重新连接成功 (尝试 {attempt}/{MaxReconnectAttempts})");
                        
                        // 验证连接可用性
                        if (await ValidatePLCConnection())
                        {
                            _mqttTopicLogger.WriteSystemInfo("PLC连接验证通过");
                            
                            // 如果数据采集任务还没有启动，现在启动它
                            if (!_dataCollectionTaskStarted)
                            {
                                _mqttTopicLogger.WriteSystemInfo("检测到数据采集任务未启动，准备启动...");
                                await StartDataCollectionTask();
                            }
                            
                    return true;
                        }
                        else
                        {
                            _mqttTopicLogger.WriteSystemError("PLC连接验证失败，尝试下一次重连");
                        }
                    }
                    else
                    {
                        _mqttTopicLogger.WriteSystemError($"PLC重连失败 (尝试 {attempt}/{MaxReconnectAttempts})");
                    }
                }
                catch (Exception ex)
                {
                    _mqttTopicLogger.WriteSystemError($"PLC重连过程中出错 (尝试 {attempt}/{MaxReconnectAttempts}): {ex.Message}");
                }

                if (attempt < MaxReconnectAttempts)
                {
                    _mqttTopicLogger.WriteSystemInfo($"等待 {ReconnectionInterval}ms 后进行下次重连尝试");
                    await Task.Delay(ReconnectionInterval, ct);
                }
            }
            
            _mqttTopicLogger.WriteSystemError($"PLC重新连接完全失败，已尝试 {MaxReconnectAttempts} 次，目标地址: {PlcIpAddress}:{PlcPort}");
            return false;
        }

        /// <summary>
        /// 验证PLC连接可用性
        /// </summary>
        /// <returns></returns>
        private async Task<bool> ValidatePLCConnection()
        {
            try
            {
                if (_plcWrapper == null || !_plcWrapper.IsConnected)
                {
                    _mqttTopicLogger.WriteSystemError("PLC连接状态检查失败：包装器为空或未连接");
                    return false;
                }

                // 尝试读取一个最小的数据块来验证连接
                if (_collectionGroups.Any())
                {
                    var firstGroup = _collectionGroups.First().Value;
                    var testRequest = new PLCDataReadRequest
                    {
                        StartAddress = firstGroup.StartAddress,
                        Length = 1, // 只读1个寄存器用于测试
                        StorageName = "ConnectionTest",
                        DataType = PLCDataType.Short // 连接测试使用简单的Short类型
                    };

                    _mqttTopicLogger.WriteSystemInfo($"验证PLC连接：读取测试地址 {firstGroup.StartAddress}");
                    var result = await _plcWrapper._dataReader.ReadDataAsync(testRequest);
                    
                    if (result.IsSuccess && result.Data != null)
                    {
                        _mqttTopicLogger.WriteSystemInfo("PLC连接验证成功：测试读取正常");
                        return true;
                    }
                    else
                    {
                        _mqttTopicLogger.WriteSystemError($"PLC连接验证失败：测试读取失败 - {result.ErrorMessage}");
                        return false;
                    }
                }
                else
                {
                    _mqttTopicLogger.WriteSystemError("PLC连接验证跳过：没有配置的采集组");
                    return true; // 如果没有配置组，假设连接有效
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"PLC连接验证过程中出错: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// PLC数据分类解析
        /// </summary>
        /// <param name="source"></param>
        /// <param name="acquisitionTypeName"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private async Task ProcessPLCData(string source, string acquisitionTypeName, byte[] data)
        {
            try
            {
                if (!Enum.TryParse<AcquisitionType>(acquisitionTypeName, out var type))
                {
                    _mqttTopicLogger.WriteSystemError($"无法解析采集类型: {acquisitionTypeName}");
                    return;
                }
                var typeConfigs = GetTypeConfigs(type).ToList();
                bool hasChanges = false;
                List<StationData> processedValues = null;


                // 基于配置选择处理方式
                if (_acquisitionTypeConfigs.TryGetValue(type, out var typeConfig))
                {
                    if (!typeConfig.IsEnabled)
                    {
                        _mqttTopicLogger.WriteSystemInfo($"跳过禁用的采集类型: {typeConfig.Name}");
                        return;
                    }

                    switch (typeConfig.ProcessType.ToUpper())
                    {
                        case "PPM":
                            if (data != null)
                            {
                                var ppmResult = ProcessShortAndFloatData(type, data, typeConfigs);
                                hasChanges = ppmResult.hasChanges;
                                processedValues = ppmResult.values;
                            }
                            break;

                        case "FLOAT":
                            if (data != null)
                            {
                                var floatResult = ProcessFloatData(type, data, typeConfigs);
                                hasChanges = floatResult.hasChanges;
                                processedValues = floatResult.values;
                            }
                            break;

                        case "ROBOT":
                            var robotResult = ProcessRobotData(type, data, typeConfigs);
                            hasChanges = robotResult.hasChanges;
                            processedValues = robotResult.jsonData;
                            break;

                        case "PARAMETER":
                            if (data != null)
                            {
                                // 参数类型按Float数据处理
                                var paramResult = ProcessFloatData(type, data, typeConfigs);
                                hasChanges = paramResult.hasChanges;
                                processedValues = paramResult.values;
                            }
                            break;

                        default:
                            _mqttTopicLogger.WriteSystemError($"不支持的处理类型: {typeConfig.ProcessType} (采集类型: {typeConfig.Name})");
                            return;
                    }
                }
                else
                {
                    // 向后兼容：如果没有配置，使用默认逻辑（基于原有的枚举类型判断）
                    _mqttTopicLogger.WriteSystemInfo($"采集类型 {type} 没有配置，使用默认处理逻辑");

                switch (type)
                {
                    case AcquisitionType.PPM:
                        if (data != null)
                        {
                            var ppmResult = ProcessShortAndFloatData(type, data, typeConfigs);
                            hasChanges = ppmResult.hasChanges;
                            processedValues = ppmResult.values;
                        }
                        break;

                    case AcquisitionType.Axis:
                    case AcquisitionType.Cylinder:
                        if (data != null)
                        {
                            var floatResult = ProcessFloatData(type, data, typeConfigs);
                            hasChanges = floatResult.hasChanges;
                            processedValues = floatResult.values;
                        }
                        break;

                        default:
                            // 默认按Robot处理
                        var robotResult = ProcessRobotData(type, data, typeConfigs);
                        hasChanges = robotResult.hasChanges;
                        processedValues = robotResult.jsonData;
                        break;
                    }
                }



                if (hasChanges && processedValues != null)
                {

                    // 上传到MQTT服务器
                    await UpMQTTServerDataNew(source, type, processedValues);
                }
                else
                {
                    _mqttTopicLogger.WriteSystemInfo($"{type} 数据未改变，未上传");
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"处理 PLC 数据时出错（源: {source}, 类型: {acquisitionTypeName}): {ex.Message}");
            }
        }


        /// <summary>
        /// 上传到MQTT里面去
        /// </summary>
        /// <param name="source"></param>
        /// <param name="type"></param>
        /// <param name="processedValues"></param>
        /// <returns></returns>
        public async Task UpMQTTServerDataNew(string source, AcquisitionType type, List<StationData> processedValues)
        {
            try
            {
                if (processedValues == null || processedValues.Count == 0)
                {
                    return;
                }

                if (!_acquisitionTypeConfigs.TryGetValue(type, out var typeConfig))
                {
                    _mqttTopicLogger.WriteSystemError($"未找到类型 {type} 的配置信息");
                    return;
                }

                var messageJson = MqttDataService.CreateMqttMessage(source, type, processedValues, _plcAddresses, _collectionGroups, typeConfig);
                if (messageJson == null && !typeConfig.IsRobot)
                {
                    _mqttTopicLogger.WriteSystemError($"类型 {type} 的消息创建失败");
                    return;
                }

                string publishTopic = typeConfig.MqttTopic;
                if (typeConfig.IsRobot)
                {
                    // 获取对应机械臂的配置
                    var groupConfig = _collectionGroups[type];
                    string robotTopicPrefix = !string.IsNullOrEmpty(typeConfig.RobotTopicPrefix) 
                        ? typeConfig.RobotTopicPrefix 
                        : DEFAULT_ROBOT_TOPIC_PREFIX;
                    string robotTopic = $"{robotTopicPrefix}{groupConfig.RobotName}";
                    _mqttTopicLogger.WriteSystemInfo($"发送机械臂数据到主题: {robotTopic} (类型: {typeConfig.Name})");
                    
                    // 记录机械臂数据发送日志
                    _mqttTopicLogger.WriteMessageSent(robotTopic, processedValues[0].AdditionalData?.ToString() ?? "空数据", source);
                    _mqttTopicLogger.WriteProcessLog(robotTopic, $"发送{typeConfig.Name}机械臂数据", "ROBOT_DATA_SEND");

                    // 使用对应的客户端发送消息到特定机械臂的主题
                    var targetClient = GetMqttClientForAcquisitionType(type);
                    var targetMqttQueue = GetMqttMessageQueueForClient(targetClient);
                    targetMqttQueue.Enqueue(source, robotTopic, type.ToString(), processedValues[0].AdditionalData);
                }
                else
                {
                    // 处理非机械臂类型的数据（PPM、Axis、Cylinder等）
                    if (messageJson != null && !string.IsNullOrEmpty(publishTopic))
                    {
                        _mqttTopicLogger.WriteSystemInfo($"发送{typeConfig.ProcessType}数据到主题: {publishTopic} (类型: {typeConfig.Name})");
                        
                        // 记录设备数据发送日志
                        _mqttTopicLogger.WriteMessageSent(publishTopic, messageJson, source);
                        _mqttTopicLogger.WriteProcessLog(publishTopic, $"发送{typeConfig.Name}设备数据，数据量: {processedValues.Count}条", "DEVICE_DATA_SEND");
                        
                        // 使用对应的客户端发送消息到指定主题
                        var targetClient = GetMqttClientForAcquisitionType(type);
                        var targetMqttQueue = GetMqttMessageQueueForClient(targetClient);
                        targetMqttQueue.Enqueue(source, publishTopic, type.ToString(), messageJson);
                    }
                    else
                    {
                        if (messageJson == null)
                        {
                            _mqttTopicLogger.WriteSystemError($"类型 {typeConfig.Name} 的消息JSON为空，无法发送");
                            _mqttTopicLogger.WriteErrorLog(publishTopic ?? "未知主题", $"类型 {typeConfig.Name} 的消息JSON为空，无法发送");
                        }
                        if (string.IsNullOrEmpty(publishTopic))
                        {
                            _mqttTopicLogger.WriteSystemError($"类型 {typeConfig.Name} 的发布主题为空，无法发送");
                            _mqttTopicLogger.WriteErrorLog("未知主题", $"类型 {typeConfig.Name} 的发布主题为空，无法发送");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"方法：上传MQTTServer数据，上传失败: {ex.Message}", ex);
            }
        }

       

        private double? ReadFloatValue(TypeConfig config, byte[] rawData, string baseAddress)
        {
            try
            {
                if (!int.TryParse(config.Address.Substring(1), out int address) ||
                    !int.TryParse(baseAddress.Substring(1), out int startAddress))
                {
                    return null;
                }

                int offset = (address - startAddress) * 2;
                if (offset < 0 || offset + 4 > rawData.Length)
                {
                    return null;
                }

                byte[] valueBytes = new byte[4];
                Array.Copy(rawData, offset, valueBytes, 0, 4);
                var value = ConvertFromBytes(valueBytes, "Float");
                return value != null ? Convert.ToDouble(value) : null;
            }
            catch
            {
                return null;
            }
        }

        private DateTime ReadTimestamp(string stationName, List<TypeConfig> timeConfigs, byte[] rawData, string baseAddress)
        {
            // 获取时间组件配置
            var hourConfig = timeConfigs.FirstOrDefault(t => t.Name == $"{stationName}_Hour");
            var minConfig = timeConfigs.FirstOrDefault(t => t.Name == $"{stationName}_Min");
            var secConfig = timeConfigs.FirstOrDefault(t => t.Name == $"{stationName}_Sec");
            var msecConfig = timeConfigs.FirstOrDefault(t => t.Name == $"{stationName}_MSec");

            // 读取时间值
            int hour = ReadShortValue(hourConfig, rawData, baseAddress);
            int minute = ReadShortValue(minConfig, rawData, baseAddress);
            int second = ReadShortValue(secConfig, rawData, baseAddress);
            int millisecond = ReadShortValue(msecConfig, rawData, baseAddress);

            // 验证时间值
            int hourInt = hour;
            int minuteInt = minute;
            int secondInt = second;
            int millisecondInt = millisecond;

            hour = (short)Math.Min(Math.Max(hourInt, 0), 23);
            minute = (short)Math.Min(Math.Max(minuteInt, 0), 59);
            second = (short)Math.Min(Math.Max(secondInt, 0), 59);
            millisecond = (short)Math.Min(Math.Max(millisecondInt, 0), 999);

            // 获取当前时间
            var now = DateTime.Now;

            // 构建读取的时间
            var readTime = new DateTime(
                now.Year,
                now.Month,
                now.Day,
                hour,
                minute,
                second,
                millisecond
            );

            // 如果读取的时间比当前时间大，说明应该是前一天的数据
            if (readTime > now)
            {
                readTime = readTime.AddDays(-1);
                _mqttTopicLogger.WriteSystemInfo($"检测到跨天数据，调整日期为前一天: {readTime:yyyy-MM-dd HH:mm:ss.fff}");
            }

            return readTime;
        }

        private int ReadShortValue(TypeConfig config, byte[] rawData, string baseAddress)
        {
            try
            {
                if (config == null || !int.TryParse(config.Address.Substring(1), out int address) ||
                    !int.TryParse(baseAddress.Substring(1), out int startAddress))
                {
                    return 0;
                }

                int offset = (address - startAddress) * 2;
                if (offset < 0 || offset + 2 > rawData.Length)
                {
                    return 0;
                }

                byte[] valueBytes = new byte[2];
                Array.Copy(rawData, offset, valueBytes, 0, 2);
                var value = ConvertFromBytes(valueBytes, "Short");
                return Convert.ToInt32(value);
            }
            catch
            {
                return 0;
            }
        }

        private object ConvertFromBytes(byte[] bytes, string dataType)
        {
            try
            {
                if (bytes == null || bytes.Length == 0)
                    return null;

                switch (dataType.ToLower())
                {
                    case "bool":
                        return BitConverter.ToInt16(bytes, 0) != 0;
                    case "short":
                        return ShortLib.GetShortFromByteArray(bytes, 0, DataFormat.CDAB);
                    case "int":
                        return IntLib.GetIntFromByteArray(bytes, 0, DataFormat.CDAB);
                    case "float":
                        return FloatLib.GetFloatFromByteArray(bytes, 0, DataFormat.CDAB);
                    default:
                        return ShortLib.GetShortFromByteArray(bytes, 0, DataFormat.CDAB);
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"转换数据类型失败: {BitConverter.ToString(bytes)} to {dataType}, {ex.Message}");
                return null;
            }
        }

        // 获取组内所有类型配置
        public IEnumerable<TypeConfig> GetTypeConfigs(AcquisitionType acquisitionType)
        {
            if (_collectionGroups.TryGetValue(acquisitionType, out var groupConfig))
            {
                return groupConfig.Types.Values;
            }
            return Enumerable.Empty<TypeConfig>();
        }

        #region 读取Short和Float类型数据
        private List<StationData> _lastStationData = new List<StationData>();

        private readonly StationDataComparer2 _comparer = new StationDataComparer2();
        /// <summary>
        /// 读取SHort和Float类型数据
        /// </summary>
        private static string LastTime = null;
        private (bool hasChanges, List<StationData> values) ProcessShortAndFloatData(AcquisitionType type, byte[] rawData, List<TypeConfig> typeConfigs)
        {
            var sw = new Stopwatch();
            sw.Start();
            _mqttTopicLogger.WriteSystemInfo($"开始新一轮数据处理");

            try
            {
                var currentStationData = new Dictionary<string, StationData>();
                bool hasNewData = false;

                // 1. 获取所有主值配置（Float类型）
                //var mainValueConfigs = typeConfigs
                //    .Where(t => string.Equals(t.DataType, "Float", StringComparison.OrdinalIgnoreCase)).OrderBy(t => int.Parse(t.Address.Substring(1))) .ToList();


                var mainValueConfigs = typeConfigs
                .Where(t => string.Equals(t.DataType, "Float", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(t.Name, "PPM", StringComparison.OrdinalIgnoreCase)) // 增加对 Name 的判断
               .OrderBy(t => int.Parse(t.Address.Substring(1))).ToList();

                _mqttTopicLogger.WriteSystemInfo($"找到 {mainValueConfigs.Count} 个Float类型配置");

                // 2. 获取所有时间配置（Short类型）
                var timeConfigs = typeConfigs
                    .Where(t => string.Equals(t.DataType, "Short", StringComparison.OrdinalIgnoreCase))
                    .ToList();

                // 3. 首先读取所有工位的当前值和时间戳
                // 全局变量，保存上次 PPM 的时间


                // 在循环外部获取当前时间
                var currentTime = DateTime.Now;

                foreach (var mainConfig in mainValueConfigs)
                {
                    string stationName = mainConfig.Name;

                    // 根据 DataType 选择读取方法
                    double? mainValue;
                    if (string.Equals(mainConfig.DataType, "Float", StringComparison.OrdinalIgnoreCase))
                    {
                        // 如果 DataType 是 Float，使用 ReadFloatValue
                        mainValue = ReadFloatValue(mainConfig, rawData, typeConfigs[0].Address);
                    }
                    else if (string.Equals(mainConfig.DataType, "Short", StringComparison.OrdinalIgnoreCase))
                    {
                        // 如果 DataType 是 Short，使用 ReadShortValue
                        mainValue = ReadShortValue(mainConfig, rawData, typeConfigs[0].Address);
                    }
                    else
                    {
                        // 其他 DataType 不支持
                        _mqttTopicLogger.WriteSystemInfo($"工位 {stationName} 的 DataType 不支持: {mainConfig.DataType}");
                        continue;
                    }

                    // 检查主值是否有效
                    if (mainValue == null || mainValue <= 0)
                    {
                        _mqttTopicLogger.WriteSystemInfo($"工位 {stationName} 主值无效: {mainValue}");
                        continue;
                    }

                    // 读取时间组件
                    // 读取时间组件
                    DateTime timestamp;
                    if (string.Equals(stationName, "PPM", StringComparison.OrdinalIgnoreCase) || string.Equals(stationName, "TotalTime", StringComparison.OrdinalIgnoreCase))
                    {
                        // 如果 Name 是 PPM，检查时间差
                        if (!string.IsNullOrEmpty(LastTime) && DateTime.TryParse(LastTime, out var lastTime))
                        {
                            // 计算时间差
                            if ((currentTime - lastTime).TotalMinutes >= 1)
                            {
                                // 如果时间差达到 1 分钟，使用当前时间
                                timestamp = currentTime;
                                LastTime = currentTime.ToString("yyyy-MM-dd HH:mm:ss.fff"); // 更新 LastTime
                            }
                            else
                            {
                                // 如果时间差不足 1 分钟，跳过当前数据
                                _mqttTopicLogger.WriteSystemInfo($"工位 {stationName} 时间差不足 1 分钟，跳过数据");
                                continue;
                            }
                        }
                        else
                        {
                            // 如果 LastTime 为空或解析失败，使用当前时间
                            timestamp = currentTime;
                            LastTime = currentTime.ToString("yyyy-MM-dd HH:mm:ss.fff"); // 更新 LastTime
                        }
                    }
                    else
                    {
                        // 否则，正常读取时间
                        timestamp = ReadTimestamp(stationName, timeConfigs, rawData, typeConfigs[0].Address);
                    }

                    // 添加到当前数据集合
                    currentStationData[stationName] = new StationData
                    {
                        Name = stationName,
                        MainValue = mainValue,
                        Timestamp = timestamp
                    };

                    _mqttTopicLogger.WriteSystemInfo($"读取工位数据: {stationName}, 值: {mainValue}, 时间: {timestamp:HH:mm:ss.fff}");
                }



                // 4. 比较新旧数据，确定是否有变化
                if (currentStationData.Any())
                {
                    if (_lastStationData == null || !_lastStationData.Any())
                    {
                        hasNewData = true;
                        _mqttTopicLogger.WriteSystemInfo("首次数据采集，记录所有数据");
                    }
                    else
                    {
                        // 检查每个工位的数据是否有变化
                        foreach (var current in currentStationData.Values)
                        {
                            var lastData = _lastStationData.FirstOrDefault(x => x.Name == current.Name);
                            if (lastData == null)
                            {
                                hasNewData = true;
                                _mqttTopicLogger.WriteSystemInfo($"发现新工位数据: {current.Name}");
                                break;
                            }

                            // 检查值和时间戳是否都有变化
                            bool valueChanged = Math.Abs(Convert.ToDouble(lastData.MainValue) - Convert.ToDouble(current.MainValue)) > 0.001;
                            bool timeChanged = Math.Abs((current.Timestamp - lastData.Timestamp).TotalMilliseconds) >= 200;

                            if (valueChanged || timeChanged)
                            {
                                hasNewData = true;
                                _mqttTopicLogger.WriteSystemInfo($"工位 {current.Name} 数据发生变化 - 值变化: {valueChanged}, 时间变化: {timeChanged}");
                                break;
                            }
                        }
                    }
                }

                // 5. 如果有新数据，更新最后处理的数据
                var resultList = currentStationData.Values.ToList();
                if (hasNewData)
                {
                    _lastStationData = new List<StationData>(resultList);
                    _mqttTopicLogger.WriteSystemInfo($"更新状态数据，数量: {resultList.Count}");
                }

                sw.Stop();
                _mqttTopicLogger.WriteSystemInfo($"处理完成，耗时: {sw.ElapsedMilliseconds}ms, 数据点数量: {resultList.Count}, 有变化: {hasNewData}");

                return (hasNewData, resultList);
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"数据处理错误: {ex.Message}\n{ex.StackTrace}");
                return (false, new List<StationData>());
            }
        }
        #endregion

        #region 机械臂
        private (bool hasChanges, List<StationData> jsonData) ProcessRobotData(AcquisitionType type, object data, List<TypeConfig> typeConfigs)
        {
            var sw = Stopwatch.StartNew();
            _mqttTopicLogger.WriteSystemInfo($"开始处理{type}数据");

            try
            {
                var rawData = data as byte[];
                if (rawData == null || !rawData.Any())
                {
                    _mqttTopicLogger.WriteSystemError("机械臂数据为空或格式错误");
                    return (false, null);
                }

                // 获取机械臂组配置
                var groupConfig = _collectionGroups[type];
                string robotName = groupConfig.RobotName;
                string groupPrefix = type.ToString();

                // 创建一个字典来存储解析后的数据
                var plcData = new Dictionary<string, short>();
                var workStationStatus = new Dictionary<string, (short status, DateTime timestamp)>();

                // 处理所有配置项，将数据解析为short类型
                foreach (var config in typeConfigs)
                {
                    try
                    {
                        if (!int.TryParse(config.Address.Substring(1), out int address))
                        {
                            _mqttTopicLogger.WriteSystemError($"无效的地址格式: {config.Address}");
                            continue;
                        }

                        int startAddress = int.Parse(typeConfigs[0].Address.Substring(1));
                        int offset = (address - startAddress) * 2;

                        if (offset < 0 || offset + 2 > rawData.Length)
                        {
                            _mqttTopicLogger.WriteSystemError($"数据偏移量超出范围: {offset}, 数据长度: {rawData.Length}");
                            continue;
                        }

                        byte[] valueBytes = new byte[2];
                        Array.Copy(rawData, offset, valueBytes, 0, 2);
                        var value = ConvertFromBytes(valueBytes, "Short");
                        if (value != null)
                        {
                            string key = $"{groupPrefix}_{config.Name}";
                            plcData[key] = Convert.ToInt16(value);
                        }
                    }
                    catch (Exception ex)
                    {
                        _mqttTopicLogger.WriteSystemError($"处理配置项 {config.Name} 时出错: {ex.Message}");
                        continue;
                    }
                }

                // 1. 获取机械臂状态
                var robotStatusConfig = typeConfigs.FirstOrDefault(c => c.Name.Contains("Robot") && c.Name.EndsWith("_Status"));
                if (robotStatusConfig == null || !plcData.TryGetValue($"{groupPrefix}_{robotStatusConfig.Name}", out short robotStatus))
                {
                    _mqttTopicLogger.WriteSystemError($"无法获取机械臂状态，组：{groupPrefix}，配置名称：{(robotStatusConfig?.Name ?? "未找到")}");
                    return (false, null);
                }

                _mqttTopicLogger.WriteSystemInfo($"成功获取机械臂状态：{robotStatusConfig.Name} = {robotStatus}");

                // 2. 处理每个工位的状态和时间戳
                string robotNumber = robotStatusConfig.Name.Replace("Robot", "").Split('_')[0];
                var actions = BASE_ACTIONS.Select(action => $"{action}{robotNumber}").ToArray();

                foreach (string action in actions)
                {
                    string statusKey = $"{groupPrefix}_{action}_Status";
                    if (plcData.TryGetValue(statusKey, out short status))
                    {
                        if (TryGetWorkstationTimestamp(action, plcData, out DateTime timestamp, groupPrefix))
                        {
                            workStationStatus[$"{groupPrefix}_{action}"] = (status, timestamp);
                        }
                    }
                }

                // 3. 确定当前激活的动作
                var currentAction = DetermineCurrentAction(workStationStatus, groupPrefix);
                
                // 4. 获取当前时间点
                double timepoint = GetFixedTimepoint(currentAction.action);
                _mqttTopicLogger.WriteSystemInfo($"使用固定时间点值: {timepoint} 秒，动作: {currentAction.action}");

                // 5. 检查状态是否变化
                string stateKey = $"{type}_{robotName}";
                bool hasChanges = false;

                if (!_lastRobotStates.TryGetValue(stateKey, out var lastState))
                {
                    hasChanges = true;
                }
                else
                {
                    hasChanges = lastState.RobotStatus != robotStatus.ToString() ||
                                lastState.CurrentAction != currentAction.action ||
                                lastState.HandStatus != currentAction.handStatus ||
                                Math.Abs(lastState.TimePoint - timepoint) > 0.1;
                }

                if (!hasChanges)
                {
                    sw.Stop();
                    _mqttTopicLogger.WriteSystemInfo($"状态未变化，处理耗时: {sw.ElapsedMilliseconds}ms");
                    return (false, null);
                }

                // 6. 准备JSON数据
                var jsonData = new
                {
                    device_time = GetMicroTimestamp(),
                    robot_name = robotName,
                    robot_status = robotStatus.ToString(),
                    action = currentAction.action.Substring(0),
                    timespan = timepoint.ToString("0.0"),
                    upload_mode = _uploadMode,
                    timepoint = 0,
                    hand_status = currentAction.handStatus.ToString()
                };

                string jsonString = JsonConvert.SerializeObject(jsonData);

                // 7. 更新最后状态
                _lastRobotStates[stateKey] = new RobotState
                {
                    RobotStatus = robotStatus.ToString(),
                    CurrentAction = currentAction.action,
                    HandStatus = currentAction.handStatus,
                    TimePoint = timepoint,
                    Timestamp = DateTime.Now
                };

                sw.Stop();
                _mqttTopicLogger.WriteSystemInfo($"生成JSON数据: {jsonString}, 处理耗时: {sw.ElapsedMilliseconds}ms");

                var stationDataList = new List<StationData>
                {
                    new StationData
                    {
                        Name = $"{type}_RobotStatus",
                        MainValue = robotStatus,
                        Timestamp = DateTime.Now,
                        AdditionalData = jsonString
                    }
                };

                return (true, stationDataList);
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"处理机械臂数据错误: {ex.Message}\n{ex.StackTrace}");
                return (false, null);
            }
        }

        private bool TryGetWorkstationTimestamp(string action, Dictionary<string, short> plcData, out DateTime timestamp, string groupPrefix)
        {
            timestamp = DateTime.Now;
            try
            {
                if (plcData.TryGetValue($"{groupPrefix}_{action}_Hour", out short hour) &&
                    plcData.TryGetValue($"{groupPrefix}_{action}_Min", out short minute) &&
                    plcData.TryGetValue($"{groupPrefix}_{action}_Sec", out short second) &&
                    plcData.TryGetValue($"{groupPrefix}_{action}_MSec", out short millisecond))
                {
                    // 验证时间值
                    int hourInt = hour;
                    int minuteInt = minute;
                    int secondInt = second;
                    int millisecondInt = millisecond;

                    hour = (short)Math.Min(Math.Max(hourInt, 0), 23);
                    minute = (short)Math.Min(Math.Max(minuteInt, 0), 59);
                    second = (short)Math.Min(Math.Max(secondInt, 0), 59);
                    millisecond = (short)Math.Min(Math.Max(millisecondInt, 0), 999);

                    var now = DateTime.Now;
                    timestamp = new DateTime(now.Year, now.Month, now.Day, hour, minute, second, millisecond);

                    // 如果时间戳大于当前时间，认为是前一天的数据
                    if (timestamp > now)
                    {
                        timestamp = timestamp.AddDays(-1);
                    }

                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"解析工位 {action} 时间戳失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 时间变换
        /// </summary>
        /// <returns></returns>
        private string GetMicroTimestamp()
        {
            var utcNow = DateTime.UtcNow;
            var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            var totalMicroseconds = (long)((utcNow - unixEpoch).TotalMilliseconds * 1000);
            return totalMicroseconds.ToString();
        }



        private (string action, short handStatus) DetermineCurrentAction(Dictionary<string, (short status, DateTime timestamp)> workStationStatus, string groupPrefix)
        {
            try
            {
                string currentAction = "";
                short handStatus = 0;
                DateTime latestTimestamp = DateTime.MinValue;

                // 遍历所有工位状态
                foreach (var kvp in workStationStatus)
                {
                    // 只处理当前组的工位
                    if (!kvp.Key.StartsWith(groupPrefix))
                    {
                        continue;
                    }

                    var (status, timestamp) = kvp.Value;

                    // 检查状态是否为激活状态（状态值为1）
                    if (status == 1)
                    {
                        // 如果找到更新的时间戳，更新当前动作
                        if (timestamp > latestTimestamp)
                        {
                            latestTimestamp = timestamp;
                            // 从键名中提取动作名称（移除组前缀）
                            currentAction = kvp.Key.Replace($"{groupPrefix}_", "");
                            handStatus = status;
                        }
                    }
                }

                if (string.IsNullOrEmpty(currentAction))
                {
                    _mqttTopicLogger.WriteSystemInfo($"没有找到活动的工位状态 (组前缀: {groupPrefix})");
                    return ("", 0);
                }

                _mqttTopicLogger.WriteSystemInfo($"确定当前动作: {currentAction}, 手状态: {handStatus}");
                return (currentAction, handStatus);
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"确定当前动作时出错: {ex.Message}");
                return ("", 0);
            }
        }

        private double GetFixedTimepoint(string action)
        {
            if (string.IsNullOrEmpty(action)) return 0.0;
            
            // 提取基础动作字母（A-H）
            string baseAction = new string(action.TakeWhile(char.IsLetter).ToArray());
            
            if (ACTION_TIMEPOINTS.TryGetValue(baseAction, out double timepoint))
            {
                return timepoint;
            }
            return 0.0;
        }
        #endregion

        #region 单独读取Float数据类型
        // 相应地，ProcessFloatData方法也需要修改返回类型

        private List<StationData> _lastFloatStationData = new List<StationData>();
        private (bool hasChanges, List<StationData> values) ProcessFloatData(AcquisitionType type, byte[] rawData, List<TypeConfig> typeConfigs)
        {
            bool hasChanges = false;
            var currentValues = new DataValue[typeConfigs.Count];

            // 记录实际需要处理的数据点数量
            _mqttTopicLogger.WriteSystemInfo($"开始处理数据: typeConfigs.Count={typeConfigs.Count}, rawData.Length={rawData.Length}");
            var sw = new Stopwatch();
            sw.Restart();
            // 初始化数组为完整的大小
            currentValues = new DataValue[typeConfigs.Count];
            var stationDataList = new List<StationData>();

            try
            {
                // 第一步：处理所有Float类型数据（主数据）
                var floatConfigs = typeConfigs.Where(t => t.DataType.Equals("Float", StringComparison.OrdinalIgnoreCase)).ToList();
                foreach (var config in floatConfigs)
                {
                    // 从地址中提取偏移量
                    if (int.TryParse(config.Address.Substring(1), out int address))
                    {
                        int startAddress = int.Parse(typeConfigs[0].Address.Substring(1));
                        int offset = (address - startAddress) * 2;

                        if (offset >= 0 && offset + 4 <= rawData.Length)
                        {
                            byte[] valueBytes = new byte[4];
                            for (int j = 0; j < 4; j++)
                            {
                                valueBytes[j] = (byte)(Convert.ToInt32(rawData[offset + j]) & 0xFF);
                            }

                            object convertedValue = ConvertFromBytes(valueBytes, "Float");
                            int index = typeConfigs.IndexOf(config);
                            currentValues[index] = new DataValue
                            {
                                Name = config.Name,
                                Value = convertedValue,
                                DataType = config.DataType
                            };
                        }
                    }
                }

                // 第二步：处理所有Short类型数据
                var shortConfigs = typeConfigs.Where(t => t.DataType.Equals("Short", StringComparison.OrdinalIgnoreCase)).ToList();
                foreach (var config in shortConfigs)
                {
                    if (int.TryParse(config.Address.Substring(1), out int address))
                    {
                        int startAddress = int.Parse(typeConfigs[0].Address.Substring(1));
                        int offset = (address - startAddress) * 2;

                        if (offset >= 0 && offset + 2 <= rawData.Length)
                        {
                            byte[] valueBytes = new byte[2];
                            for (int j = 0; j < 2; j++)
                            {
                                valueBytes[j] = (byte)(Convert.ToInt32(rawData[offset + j]) & 0xFF);
                            }

                            object convertedValue = ConvertFromBytes(valueBytes, "Short");
                            int index = typeConfigs.IndexOf(config);
                            currentValues[index] = new DataValue
                            {
                                Name = config.Name,
                                Value = convertedValue,
                                DataType = config.DataType
                            };
                        }
                    }
                }

                // 第三步：组织StationData列表

                foreach (var floatConfig in floatConfigs)
                {
                    string baseName = floatConfig.Name;  // 例如 "S_MagLev"
                    var mainValue = currentValues[typeConfigs.IndexOf(floatConfig)]?.Value;
                    // 先获取MainValue，如果为0则跳过这个工位,暂时不过滤
                    //if (mainValue == null || Convert.ToDouble(mainValue) == 0)
                    //{
                    //    _mqttTopicLogger.WriteSystemInfo($"跳过工位 {baseName}: MainValue为0或null");
                    //    continue;
                    //}

                    // 只检查MainValue是否与上一次的值相同，暂时不检查
                    //var lastData = _lastStationData.FirstOrDefault(x => x.Name == baseName);
                    //if (lastData != null)
                    //{
                    //    bool valueEqual = Convert.ToDouble(lastData.MainValue) == Convert.ToDouble(mainValue);

                    //    if (valueEqual)
                    //    {
                    //        _mqttTopicLogger.WriteSystemInfo($"跳过工位 {baseName}: 值未变化 当前值:{mainValue}");
                    //        continue;
                    //    }

                    //    _mqttTopicLogger.WriteSystemInfo($"工位 {baseName} 数值发生变化: {lastData.MainValue} -> {mainValue}");
                    //}

                    // 创建StationData对象
                    var stationData = new StationData
                    {
                        Name = baseName,
                        MainValue = mainValue,
                        Timestamp = DateTime.Now,
                    };

                    stationDataList.Add(stationData);
                    _mqttTopicLogger.WriteSystemInfo($"添加工位数据: {stationData.Name}, 值: {stationData.MainValue}, 时间戳: {stationData.Timestamp:HH:mm:ss.fff}");
                }

                // 检查是否有新数据需要更新
                if (stationDataList.Any())
                {
                    hasChanges = true;  // 如果有数据通过过滤，就表示有变化

                    // 创建深拷贝以避免引用问题
                    _lastFloatStationData = stationDataList.Select(s => new StationData
                    {
                        Name = s.Name,
                        MainValue = s.MainValue,
                        Timestamp = s.Timestamp
                    }).ToList();

                    _lastFloatStationData = stationDataList;//把当前的新数据赋值到旧的集合中


                    //// 记录变化信息
                    //foreach (var newData in stationDataList)
                    //{
                    //    _mqttTopicLogger.WriteSystemInfo($"工位 {newData.Name} 更新: 时间戳: {newData.Timestamp:HH:mm:ss.fff}, 值: {newData.MainValue}");
                    //}
                }
                else
                {
                    _mqttTopicLogger.WriteSystemInfo("没有发现时间戳变化的数据");
                    hasChanges = false;
                }


                sw.Stop();
                _mqttTopicLogger.WriteSystemInfo($"处理结束耗时：{sw.ElapsedMilliseconds}ms");
                return (hasChanges, stationDataList);
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"处理数据时出错: {ex.Message}");
                return (false, stationDataList);
            }

        }
        #endregion
    }


    public class PLCDataParser
    {
        private readonly Dictionary<string, TypeConfig> _globalConfigs;
        private readonly ConcurrentDictionary<string, Dictionary<string, TypeConfig>> _groupConfigsCache;

        public PLCDataParser(IEnumerable<TypeConfig> globalConfigs)
        {
            _globalConfigs = globalConfigs?.ToDictionary(t => t.Name, t => t)
                ?? new Dictionary<string, TypeConfig>();
            _groupConfigsCache = new ConcurrentDictionary<string, Dictionary<string, TypeConfig>>();
        }

        public Dictionary<string, object> ParseGroupData(byte[] rawData, string groupStartAddress, int groupLength, IEnumerable<TypeConfig> groupConfigs = null)
        {
            if (rawData == null || rawData.Length == 0)
            {
                _mqttTopicLogger.WriteSystemError("原始数据为空");
                return new Dictionary<string, object>();
            }

            try
            {
                // 使用缓存获取或创建组配置
                var currentGroupConfigs = GetOrCreateGroupConfigs(groupStartAddress, groupLength, groupConfigs);

                // 验证数据长度
                int requiredBytes = groupLength * 2;
                if (rawData.Length < requiredBytes)
                {
                    _mqttTopicLogger.WriteSystemError($"数据长度不足: 需要 {requiredBytes} 字节，实际 {rawData.Length} 字节");
                    return new Dictionary<string, object>();
                }

                int baseAddress = ParseAddress(groupStartAddress);
                var result = new Dictionary<string, object>();

                foreach (var config in currentGroupConfigs.Values)
                {
                    try
                    {
                        if (!int.TryParse(config.Address?.Substring(1), out int address))
                        {
                            _mqttTopicLogger.WriteSystemError($"无效的地址格式: {config.Address}");
                            continue;
                        }

                        int offset = (address - baseAddress) * 2;

                        switch (config.DataType.ToLower())
                        {
                            case "float":
                                if (offset < 0 || offset + 4 > rawData.Length)
                                {
                                    _mqttTopicLogger.WriteSystemError($"Float数据地址 {config.Address} 超出范围");
                                    continue;
                                }
                                byte[] floatBytes = new byte[4];
                                Array.Copy(rawData, offset, floatBytes, 0, 4);
                                var floatValue = FloatLib.GetFloatFromByteArray(floatBytes, 0, DataFormat.CDAB);
                                result[config.Name] = floatValue;
                                break;

                            case "short":
                                if (offset < 0 || offset + 2 > rawData.Length)
                                {
                                    _mqttTopicLogger.WriteSystemError($"Short数据地址 {config.Address} 超出范围");
                                    continue;
                                }
                                byte[] shortBytes = new byte[2];
                                Array.Copy(rawData, offset, shortBytes, 0, 2);
                                var shortValue = ShortLib.GetShortFromByteArray(shortBytes, 0, DataFormat.CDAB);
                                result[config.Name] = shortValue;
                                break;

                            case "int":
                                if (offset < 0 || offset + 4 > rawData.Length)
                                {
                                    _mqttTopicLogger.WriteSystemError($"Int数据地址 {config.Address} 超出范围");
                                    continue;
                                }
                                byte[] intBytes = new byte[4];
                                Array.Copy(rawData, offset, intBytes, 0, 4);
                                var intValue = IntLib.GetIntFromByteArray(intBytes, 0, DataFormat.CDAB);
                                result[config.Name] = intValue;
                                break;

                            case "bool":
                                if (offset < 0 || offset + 2 > rawData.Length)
                                {
                                    _mqttTopicLogger.WriteSystemError($"Bool数据地址 {config.Address} 超出范围");
                                    continue;
                                }
                                byte[] boolBytes = new byte[2];
                                Array.Copy(rawData, offset, boolBytes, 0, 2);
                                var boolValue = BitConverter.ToInt16(boolBytes, 0) != 0;
                                result[config.Name] = boolValue;
                                break;

                            default:
                                _mqttTopicLogger.WriteSystemError($"不支持的数据类型: {config.DataType}, 配置项: {config.Name}");
                                continue;
                        }

                        _mqttTopicLogger.WriteSystemInfo($"成功解析 {config.Name} ({config.DataType}): {result[config.Name]}");
                    }
                    catch (Exception ex)
                    {
                        _mqttTopicLogger.WriteSystemError($"处理配置 {config.Name} 时出错: {ex.Message}");
                    }
                }

                return result;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"解析组数据时出错: {ex.Message}");
                return new Dictionary<string, object>();
            }
        }

        private Dictionary<string, TypeConfig> GetOrCreateGroupConfigs(
            string startAddress,
            int length,
            IEnumerable<TypeConfig> groupConfigs)
        {
            string cacheKey = $"{startAddress}_{length}";

            return _groupConfigsCache.GetOrAdd(cacheKey, _ =>
            {
                if (groupConfigs?.Any() == true)
                {
                    return groupConfigs.ToDictionary(t => t.Name, t => t);
                }

                int baseAddr = ParseAddress(startAddress);
                return _globalConfigs.Where(kv => IsAddressInGroup(kv.Value.Address, baseAddr, length)).ToDictionary(kv => kv.Key, kv => kv.Value);
            });
        }

        private bool IsAddressInGroup(string address, int baseAddress, int length)
        {
            if (string.IsNullOrEmpty(address) || !address.StartsWith("D"))
            {
                return false;
            }

            try
            {
                int addr = ParseAddress(address);
                return addr >= baseAddress && addr < baseAddress + length;
            }
            catch
            {
                return false;
            }
        }

        private static int ParseAddress(string address)
        {
            if (string.IsNullOrEmpty(address) || !address.StartsWith("D") ||
                !int.TryParse(address.Substring(1), out int num))
            {
                throw new ArgumentException($"无效的PLC地址格式: {address} (示例: D24500)");
            }
            return num;
        }
    }
    /// <summary>
    /// 时间转化
    /// </summary>

    public static class DateTimeExtensions
    {
        public static long ToUnixTimeMilliseconds(this DateTime dateTime)
        {
            return (long)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
        }

        public static long GetUnixTimestamp()
        {
            return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
        }
    }

    // 辅助类
    public class DataValue
    {
        public string Name { get; set; }
        public object Value { get; set; }
        public string DataType { get; set; }

        public override bool Equals(object obj)
        {
            if (obj is DataValue other)
            {
                if (Value == null && other.Value == null) return true;
                if (Value == null || other.Value == null) return false;

                switch (DataType.ToLower())
                {
                    case "float":
                        if (Value is float f1 && other.Value is float f2)
                            return Math.Abs(f1 - f2) < 0.000001f;
                        break;
                    case "bool":
                        if (Value is bool b1 && other.Value is bool b2)
                            return b1 == b2;
                        break;
                }

                return Value.Equals(other.Value);
            }
            return false;
        }

        public override int GetHashCode()
        {
            return Value?.GetHashCode() ?? 0;
        }
    }
}

